]> git.pld-linux.org Git - packages/asterisk.git/blame - asterisk-bristuff.patch
- olddir for log archives
[packages/asterisk.git] / asterisk-bristuff.patch
CommitLineData
b3826e10 1--- a/README
2+++ b/README
3@@ -4,6 +4,8 @@ and the Asterisk.org developer community
4
5 Copyright (C) 2001-2006 Digium, Inc.
6 and other copyright holders.
7+Copyright (C) 2002-2005 Junghanns.NET GmbH
8+and other copyright holders.
9 ================================================================
10
11 * SECURITY
12--- a/LICENSE
13+++ b/LICENSE
14@@ -1,7 +1,7 @@
15-Asterisk is distributed under the GNU General Public License version 2
16-and is also available under alternative licenses negotiated directly
17-with Digium, Inc. If you obtained Asterisk under the GPL, then the GPL
18-applies to all loadable Asterisk modules used on your system as well,
19+BRIstuffed Asterisk is distributed under the GNU General Public License version 2
20+and is not available under any alternative licenses.
21+If you obtained BRIstuffed Asterisk under the GPL, then the GPL
22+applies to all loadable BRIstuffed Asterisk modules used on your system as well,
23 except as defined below. The GPL (version 2) is included in this
24 source tree in the file COPYING.
25
26--- a/doc/hardware.txt
27+++ b/doc/hardware.txt
28@@ -31,6 +31,19 @@ Zaptel compatible hardware
29 * Wildcard TE410P - Quad T1/E1 switchable interface. Supports PRI and
30 RBS signalling, as well as PPP, FR, and HDLC data modes.
31
32+-- Junghanns.NET (Primary author of BRIstuff)
33+ http://www.junghanns.net
34+
35+ * quadBRI PCI ISDN - 4port BRI ISDN interface, supports NT and TE mode
36+
37+ * octoBRI PCI ISDN - 8port BRI ISDN interface, supports NT and TE mode
38+
39+ * singleE1 PCI ISDN - Single E1 interface
40+
41+ * doubleE1 PCI ISDN - Double E1 interface
42+
43+ * uno/duo/quad GSM PCI - 1/2/4 channel GSM interface cards
44+
45 Non-zaptel compatible hardware
46 ==============================
47
48--- a/build_tools/make_defaults_h
49+++ b/build_tools/make_defaults_h
50@@ -17,6 +17,7 @@ cat << END
51 #define AST_KEY_DIR "${INSTALL_PATH}${ASTDATADIR}/keys"
52 #define AST_DB "${INSTALL_PATH}${ASTVARLIBDIR}/astdb"
53 #define AST_TMP_DIR "${INSTALL_PATH}${ASTSPOOLDIR}/tmp"
54+#define AST_SYSTEM_NAME "asterisk"
55
56 #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
57
58--- a/main/asterisk.c
59+++ b/main/asterisk.c
60@@ -2427,6 +2427,7 @@ static void ast_readconfig(void)
61 ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
62 ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
63 ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
64+ ast_copy_string(ast_config_AST_SYSTEM_NAME, AST_SYSTEM_NAME, sizeof(ast_config_AST_SYSTEM_NAME));
65
66 /* no asterisk.conf? no problem, use buildtime config! */
67 if (!cfg) {
68@@ -2551,6 +2552,8 @@ static void ast_readconfig(void)
69 ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
70 } else if (!strcasecmp(v->name, "systemname")) {
71 ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
72+ } else if (!strcasecmp(v->name, "uniquename")) {
73+ ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
74 } else if (!strcasecmp(v->name, "languageprefix")) {
75 ast_language_is_prefix = ast_true(v->value);
76 }
77--- a/include/asterisk/agi.h
78+++ b/include/asterisk/agi.h
79@@ -30,6 +30,7 @@ extern "C" {
80 typedef struct agi_state {
81 int fd; /* FD for general output */
82 int audio; /* FD for audio output */
83+ int audio_in; /* FD for audio output */
84 int ctrl; /* FD for input control */
85 unsigned int fast:1; /* flag for fast agi or not */
86 } AGI;
87--- a/res/res_agi.c
88+++ b/res/res_agi.c
89@@ -11,6 +11,9 @@
90 * the project provides a web site, mailing lists and IRC
91 * channels for your use.
92 *
93+ * Copyright (C) 2005 Junghanns.NET GmbH
94+ * Klaus-Peter Junghanns <kpj@junghanns.net>
95+ *
96 * This program is free software, distributed under the terms of
97 * the GNU General Public License Version 2. See the LICENSE file
98 * at the top of the source tree.
99@@ -75,16 +78,19 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
100
101 static char *app = "AGI";
102
103+static char *xapp = "XAGI";
104+
105 static char *eapp = "EAGI";
106
107 static char *deadapp = "DeadAGI";
108
109 static char *synopsis = "Executes an AGI compliant application";
110+static char *xsynopsis = "Executes an XAGI compliant application";
111 static char *esynopsis = "Executes an EAGI compliant application";
112 static char *deadsynopsis = "Executes AGI on a hungup channel";
113
114 static char *descrip =
115-" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
116+" [E|Dead|X]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
117 "program on a channel. AGI allows Asterisk to launch external programs\n"
118 "written in any language to control a telephony channel, play audio,\n"
119 "read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
120@@ -97,6 +103,8 @@ static char *descrip =
121 "variable to \"no\" before executing the AGI application.\n"
122 " Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
123 "on file descriptor 3\n\n"
124+"Using 'XAGI' provides enhanced AGI, with incoming audio available out of band"
125+" on file descriptor 3 and outgoing audio available out of band on file descriptor 4\n\n"
126 " Use the CLI command 'agi show' to list available agi commands\n"
127 " This application sets the following channel variable upon completion:\n"
128 " AGISTATUS The status of the attempt to the run the AGI script\n"
129@@ -236,13 +244,14 @@ static enum agi_result launch_netscript(
130 return AGI_RESULT_SUCCESS_FAST;
131 }
132
133-static enum agi_result launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
134+static enum agi_result launch_script(char *script, char *argv[], int *fds, int *efd, int *efd2, int *opid)
135 {
136 char tmp[256];
137 int pid;
138 int toast[2];
139 int fromast[2];
140 int audio[2];
141+ int audio2[2];
142 int x;
143 int res;
144 sigset_t signal_set, old_set;
145@@ -287,6 +296,33 @@ static enum agi_result launch_script(cha
146 return AGI_RESULT_FAILURE;
147 }
148 }
149+ if (efd2) {
150+ if (pipe(audio2)) {
151+ ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
152+ close(fromast[0]);
153+ close(fromast[1]);
154+ close(toast[0]);
155+ close(toast[1]);
156+ close(audio[0]);
157+ close(audio[1]);
158+ return AGI_RESULT_FAILURE;
159+ }
160+ res = fcntl(audio2[0], F_GETFL);
161+ if (res > -1)
162+ res = fcntl(audio2[0], F_SETFL, res | O_NONBLOCK);
163+ if (res < 0) {
164+ ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
165+ close(fromast[0]);
166+ close(fromast[1]);
167+ close(toast[0]);
168+ close(toast[1]);
169+ close(audio[0]);
170+ close(audio[1]);
171+ close(audio2[0]);
172+ close(audio2[1]);
173+ return AGI_RESULT_FAILURE;
174+ }
175+ }
176
177 /* Block SIGHUP during the fork - prevents a race */
178 sigfillset(&signal_set);
179@@ -322,6 +358,11 @@ static enum agi_result launch_script(cha
180 } else {
181 close(STDERR_FILENO + 1);
182 }
183+ if (efd2) {
184+ dup2(audio2[1], STDERR_FILENO + 2);
185+ } else {
186+ close(STDERR_FILENO + 2);
187+ }
188
189 /* Before we unblock our signals, return our trapped signals back to the defaults */
190 signal(SIGHUP, SIG_DFL);
191@@ -339,7 +380,7 @@ static enum agi_result launch_script(cha
192 }
193
194 /* Close everything but stdin/out/error */
195- for (x=STDERR_FILENO + 2;x<1024;x++)
196+ for (x=STDERR_FILENO + 3;x<1024;x++)
197 close(x);
198
199 /* Execute script */
200@@ -359,12 +400,19 @@ static enum agi_result launch_script(cha
201 if (efd) {
202 *efd = audio[1];
203 }
204+ if (efd2) {
205+ *efd2 = audio2[0];
206+ }
207 /* close what we're not using in the parent */
208 close(toast[1]);
209 close(fromast[0]);
210
211- if (efd)
212+ if (efd) {
213 close(audio[0]);
214+ }
215+ if (efd2) {
216+ close(audio2[1]);
217+ }
218
219 *opid = pid;
220 return AGI_RESULT_SUCCESS;
221@@ -394,7 +442,7 @@ static void setup_env(struct ast_channel
222 fdprintf(fd, "agi_context: %s\n", chan->context);
223 fdprintf(fd, "agi_extension: %s\n", chan->exten);
224 fdprintf(fd, "agi_priority: %d\n", chan->priority);
225- fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
226+ fdprintf(fd, "agi_enhanced: %d%s\n", enhanced, ".0");
227
228 /* User information */
229 fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
230@@ -1835,8 +1883,13 @@ static enum agi_result run_agi(struct as
231 int ms;
232 enum agi_result returnstatus = AGI_RESULT_SUCCESS;
233 struct ast_frame *f;
234+ struct ast_frame fr;
235 char buf[AGI_BUF_LEN];
236+ char audiobuf[AGI_BUF_LEN];
237 char *res = NULL;
238+ int audiobytes;
239+ int fds[2];
240+ int enhanced = 0;
241 FILE *readf;
242 /* how many times we'll retry if ast_waitfor_nandfs will return without either
243 channel or file descriptor in case select is interrupted by a system call (EINTR) */
244@@ -1850,10 +1903,22 @@ static enum agi_result run_agi(struct as
245 return AGI_RESULT_FAILURE;
246 }
247 setlinebuf(readf);
248- setup_env(chan, request, agi->fd, (agi->audio > -1));
249+ if (agi->audio > -1) {
250+ enhanced = 1;
251+ }
252+ if (agi->audio_in > -1) {
253+ enhanced++;
254+ }
255+ setup_env(chan, request, agi->fd, enhanced);
256+ fds[0] = agi->ctrl;
257+ fds[1] = agi->audio_in;
258 for (;;) {
259 ms = -1;
260- c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
261+ if (agi->audio_in > -1) {
262+ c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, fds, 2, NULL, &outfd, &ms);
263+ } else {
264+ c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
265+ }
266 if (c) {
267 retry = AGI_NANDFS_RETRY;
268 /* Idle the channel until we get a command */
269@@ -1871,6 +1936,16 @@ static enum agi_result run_agi(struct as
270 ast_frfree(f);
271 }
272 } else if (outfd > -1) {
273+ if ((agi->audio_in > -1) && (outfd == agi->audio_in)) {
274+ audiobytes = read(agi->audio_in, audiobuf, sizeof(audiobuf));
275+ if (audiobytes > 0) {
276+ fr.frametype = AST_FRAME_VOICE;
277+ fr.subclass = AST_FORMAT_SLINEAR;
278+ fr.datalen = audiobytes;
279+ fr.data = audiobuf;
280+ ast_write(chan, &fr);
281+ }
282+ } else {
283 size_t len = sizeof(buf);
284 size_t buflen = 0;
285
286@@ -1922,6 +1997,7 @@ static enum agi_result run_agi(struct as
287 if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
288 break;
289 }
290+ }
291 } else {
292 if (--retry <= 0) {
293 ast_log(LOG_WARNING, "No channel, no fd?\n");
294@@ -2030,6 +2106,7 @@ static int agi_exec_full(struct ast_chan
295 int argc = 0;
296 int fds[2];
297 int efd = -1;
298+ int efd2 = -1;
299 int pid;
300 char *stringp;
301 AGI agi;
302@@ -2056,12 +2133,13 @@ static int agi_exec_full(struct ast_chan
303 }
304 #endif
305 ast_replace_sigchld();
306- res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
307+ res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, (enhanced == 2) ? &efd2 : NULL, &pid);
308 if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
309 int status = 0;
310 agi.fd = fds[1];
311 agi.ctrl = fds[0];
312 agi.audio = efd;
313+ agi.audio_in = efd2;
314 agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
315 res = run_agi(chan, argv[0], &agi, pid, &status, dead);
316 /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
317@@ -2071,6 +2149,8 @@ static int agi_exec_full(struct ast_chan
318 close(fds[1]);
319 if (efd > -1)
320 close(efd);
321+ if (efd2 > -1)
322+ close(efd2);
323 }
324 ast_unreplace_sigchld();
325 ast_module_user_remove(u);
326@@ -2119,6 +2199,35 @@ static int eagi_exec(struct ast_channel
327 return res;
328 }
329
330+static int xagi_exec(struct ast_channel *chan, void *data)
331+{
332+ int readformat, writeformat;
333+ int res;
334+
335+ if (chan->_softhangup)
336+ ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
337+ readformat = chan->readformat;
338+ if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
339+ ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
340+ return -1;
341+ }
342+ writeformat = chan->writeformat;
343+ if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
344+ ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
345+ return -1;
346+ }
347+ res = agi_exec_full(chan, data, 2, 0);
348+ if (!res) {
349+ if (ast_set_read_format(chan, readformat)) {
350+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
351+ }
352+ if (ast_set_write_format(chan, writeformat)) {
353+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(writeformat));
354+ }
355+ }
356+ return res;
357+}
358+
359 static int deadagi_exec(struct ast_channel *chan, void *data)
360 {
361 if (!ast_check_hangup(chan))
362@@ -2174,6 +2283,7 @@ static int unload_module(void)
363 {
364 ast_module_user_hangup_all();
365 ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
366+ ast_unregister_application(xapp);
367 ast_unregister_application(eapp);
368 ast_unregister_application(deadapp);
369 return ast_unregister_application(app);
370@@ -2184,6 +2294,7 @@ static int load_module(void)
371 ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
372 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
373 ast_register_application(eapp, eagi_exec, esynopsis, descrip);
374+ ast_register_application(xapp, xagi_exec, xsynopsis, descrip);
375 return ast_register_application(app, agi_exec, synopsis, descrip);
376 }
377
378--- /dev/null
379+++ b/agi/xagi-test.c
380@@ -0,0 +1,175 @@
381+/*
382+ * Asterisk -- A telephony toolkit for Linux.
383+ *
384+ * XAGI sample script
385+ *
386+ * Copyright (C) 2005 Junghanns.NET GmbH
387+ * Klaus-Peter Junghanns <kpj@junghanns.net>
388+ *
389+ * based on eagi-test.c
390+ *
391+ * This program is free software, distributed under the terms of
392+ * the GNU General Public License
393+ */
394+
395+#include <stdio.h>
396+#include <unistd.h>
397+#include <stdlib.h>
398+#include <errno.h>
399+#include <string.h>
400+#include <sys/select.h>
401+#ifdef SOLARIS
402+#include <solaris-compat/compat.h>
403+#endif
404+
405+#define AUDIO_FILENO_IN (STDERR_FILENO + 1)
406+#define AUDIO_FILENO_OUT (STDERR_FILENO + 2)
407+
408+static int read_environment(void)
409+{
410+ char buf[256];
411+ char *val;
412+ /* Read environment */
413+ for(;;) {
414+ fgets(buf, sizeof(buf), stdin);
415+ if (feof(stdin))
416+ return -1;
417+ buf[strlen(buf) - 1] = '\0';
418+ /* Check for end of environment */
419+ if (!strlen(buf))
420+ return 0;
421+ val = strchr(buf, ':');
422+ if (!val) {
423+ fprintf(stderr, "Invalid environment: '%s'\n", buf);
424+ return -1;
425+ }
426+ *val = '\0';
427+ val++;
428+ val++;
429+ /* Skip space */
430+ // fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val);
431+
432+ /* Load into normal environment */
433+ setenv(buf, val, 1);
434+
435+ }
436+ /* Never reached */
437+ return 0;
438+}
439+
440+static void app_echo(void)
441+{
442+ fd_set fds;
443+ int res;
444+ int bytes = 0;
445+ static char astresp[256];
446+ char audiobuf[16000]; /* 1 second of audio */
447+ for (;;) {
448+ FD_ZERO(&fds);
449+ FD_SET(STDIN_FILENO, &fds);
450+ FD_SET(AUDIO_FILENO_IN, &fds);
451+ /* Wait for *some* sort of I/O */
452+ res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
453+ if (res < 0) {
454+ fprintf(stderr, "Error in select: %s\n", strerror(errno));
455+ return;
456+ }
457+ if (FD_ISSET(STDIN_FILENO, &fds)) {
458+ fgets(astresp, sizeof(astresp), stdin);
459+ if (feof(stdin)) {
460+ return;
461+ }
462+ astresp[strlen(astresp) - 1] = '\0';
463+ fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
464+ return;
465+ }
466+ if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
467+ /* what goes in.... */
468+ res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
469+ if (res > 0) {
470+ bytes = res;
471+ /* must come out */
472+ write(AUDIO_FILENO_OUT, audiobuf, bytes);
473+ }
474+ }
475+ }
476+}
477+
478+static char *wait_result(void)
479+{
480+ fd_set fds;
481+ int res;
482+ static char astresp[256];
483+ char audiobuf[4096];
484+ for (;;) {
485+ FD_ZERO(&fds);
486+ FD_SET(STDIN_FILENO, &fds);
487+ FD_SET(AUDIO_FILENO_IN, &fds);
488+ /* Wait for *some* sort of I/O */
489+ res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
490+ if (res < 0) {
491+ fprintf(stderr, "Error in select: %s\n", strerror(errno));
492+ return NULL;
493+ }
494+ if (FD_ISSET(STDIN_FILENO, &fds)) {
495+ fgets(astresp, sizeof(astresp), stdin);
496+ if (feof(stdin)) {
497+ fprintf(stderr, "Got hungup on apparently\n");
498+ return NULL;
499+ }
500+ astresp[strlen(astresp) - 1] = '\0';
501+ fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
502+ return astresp;
503+ }
504+ if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
505+ res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
506+ /* drop it, like it's hot */
507+ }
508+ }
509+
510+}
511+
512+static char *run_command(char *command)
513+{
514+ fprintf(stdout, "%s\n", command);
515+ return wait_result();
516+}
517+
518+
519+static int run_script(void)
520+{
521+ char *res;
522+ res = run_command("STREAM FILE demo-echotest \"\"");
523+ if (!res) {
524+ fprintf(stderr, "Failed to execute command\n");
525+ return -1;
526+ }
527+ app_echo();
528+ return 0;
529+}
530+
531+int main(int argc, char *argv[])
532+{
533+ char *tmp;
534+ int ver = 0;
535+ int subver = 0;
536+ /* Setup stdin/stdout for line buffering */
537+ setlinebuf(stdin);
538+ setlinebuf(stdout);
539+ if (read_environment()) {
540+ fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
541+ exit(1);
542+ }
543+ tmp = getenv("agi_enhanced");
544+ if (tmp) {
545+ if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
546+ ver = 0;
547+ }
548+ if (ver < 2) {
549+ fprintf(stderr, "No XAGI services available. Use XAGI, not AGI or EAGI\n");
550+ exit(1);
551+ }
552+ if (run_script())
553+ return -1;
554+ exit(0);
555+}
556--- a/agi/Makefile
557+++ b/agi/Makefile
558@@ -13,7 +13,7 @@
559
560 .PHONY: clean all uninstall
561
562-AGIS=agi-test.agi eagi-test eagi-sphinx-test jukebox.agi
563+AGIS=agi-test.agi eagi-test eagi-sphinx-test jukebox.agi xagi-test
564
565 ifeq ($(OSARCH),SunOS)
566 LIBS+=-lsocket -lnsl
567@@ -38,7 +38,7 @@ uninstall:
568 for x in $(AGIS); do rm -f $(DESTDIR)$(AGI_DIR)/$$x ; done
569
570 clean:
571- rm -f *.so *.o look eagi-test eagi-sphinx-test
572+ rm -f *.so *.o look eagi-test eagi-sphinx-test xagi-test
573 rm -f .*.o.d .*.oo.d *.s *.i
574 rm -f strcompat.c
575
576--- /dev/null
577+++ b/apps/app_segfault.c
578@@ -0,0 +1,55 @@
579+/*
580+ * Segfault application
581+ *
582+ * An application to provoke a segmentation fault from the dialplan.
583+ * (I know what you are thinking now...., but since Asterisk is too stable...
584+ * I needed something to test my failover switches.)
585+ *
586+ * Copyright (C) 2005 Junghanns.NET GmbH
587+ * Klaus-Peter Junghanns <kpj@junghanns.net>
588+ *
589+ * This program is free software, distributed under the terms of
590+ * the GNU General Public License. THIS APPLICATION _WILL_ CRASH YOUR
591+ * ASTERISK SERVER SO OF COURSE THERE IS NOT LIABILITY FOR NOTHING!
592+ */
593+
594+#include "asterisk.h"
595+
596+#include <stdlib.h>
597+#include <unistd.h>
598+#include <string.h>
599+#include <stdio.h>
600+#include <asterisk/lock.h>
601+#include <asterisk/file.h>
602+#include <asterisk/logger.h>
603+#include <asterisk/channel.h>
604+#include <asterisk/pbx.h>
605+#include <asterisk/module.h>
606+
607+static char *app = "Segfault";
608+
609+static char *synopsis = "This application will crash Asterisk with a segmentation fault.";
610+
611+static char *descrip =
612+" Segfault(): Crash with a segfault. Never returns nufin.\n";
613+
614+static int segfault_exec(struct ast_channel *chan, void *data)
615+{
616+ ((char *)0)[0] = 0;
617+ return 0;
618+}
619+
620+static int unload_module(void)
621+{
622+ return ast_unregister_application(app);
623+}
624+
625+static int load_module(void)
626+{
627+ return ast_register_application(app, segfault_exec, synopsis, descrip);
628+}
629+
630+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Application for crashing Asterisk with a segmentation fault",
631+ .load = load_module,
632+ .unload = unload_module,
633+);
634--- a/apps/app_directed_pickup.c
635+++ b/apps/app_directed_pickup.c
636@@ -45,7 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
637
638 #define PICKUPMARK "PICKUPMARK"
639
640-static const char *app = "Pickup";
641+static const char *app = "DPickup";
642 static const char *synopsis = "Directed Call Pickup";
643 static const char *descrip =
644 " Pickup(extension[@context][&extension2@context...]): This application can pickup any ringing channel\n"
645--- /dev/null
646+++ b/apps/app_pickup.c
647@@ -0,0 +1,300 @@
648+/*
649+ * Asterisk -- A telephony toolkit for Linux.
650+ *
651+ * Pickup, channel independent call pickup
652+ *
653+ * Copyright (C) 2004, Junghanns.NET GmbH
654+ *
655+ * Klaus-Peter Junghanns <kpj@junghanns.net>
656+ *
657+ * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
658+ *
659+ * This program is free software, distributed under the terms of
660+ * the GNU General Public License
661+ */
662+
663+#include "asterisk.h"
664+
665+#include <stdlib.h>
666+#include <unistd.h>
667+#include <string.h>
668+#include <stdio.h>
669+#include <signal.h>
670+#include <pthread.h>
671+#include <asterisk/lock.h>
672+#include <asterisk/file.h>
673+#include <asterisk/logger.h>
674+#include <asterisk/channel.h>
675+#include <asterisk/pbx.h>
676+#include <asterisk/module.h>
677+#include <asterisk/features.h>
678+#include <asterisk/options.h>
679+
680+
681+static char *app = "PickUp";
682+
683+static char *synopsis = "Channel independent call pickup.";
684+
685+static char *descrip =
686+" PickDown([group]): Tries to pickup the first ringing channel with callgroup == group.\n"
687+" If called without the group argument, the pickupgroup of the channel will be used.\n";
688+
689+static char *app2 = "Steal";
690+
691+static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
692+
693+static char *descrip2 =
694+" Steal([group]): Tries to steal the first bridged channel with callgroup == group.\n"
695+" If called without the group argument, the pickupgroup of the channel will be used.\n";
696+
697+static char *app3 = "PickDown";
698+
699+static char *synopsis3 = "Channel independent call pickdown.";
700+
701+static char *descrip3 =
702+" PickDown([group]): Tries to hangup the first ringing channel with callgroup == group.\n"
703+" If called without the group argument, the pickupgroup of the channel will be used.\n";
704+
705+static char *app4 = "PickupChan";
706+
707+static char *synopsis4 = "Channel independent call pickup.";
708+
709+static char *descrip4 =
710+" PickupChan(Technology/resource[&Technology2/resource2...]): Tries to pickup the first ringing channel in the parameter list.\n";
711+
712+static char *app5 = "StealChan";
713+
714+static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
715+
716+static char *descrip5 =
717+" StealChan(Technology/resource[&Technology2/resource2...]): Tries to steal the first ringing channel in the parameter list.\n";
718+
719+
720+static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
721+ struct ast_channel *cur;
722+ int res = -1;
723+ cur = ast_channel_walk_locked(NULL);
724+ while(cur) {
725+ if ((cur != chan) &&
726+ (pickupgroup & cur->callgroup) &&
727+ (cur->_state == chanstate)) {
728+ break;
729+ }
730+ ast_mutex_unlock(&cur->lock);
731+ cur = ast_channel_walk_locked(cur);
732+ }
733+ if (cur) {
734+ if(option_verbose > 2) {
735+ if (chanstate == AST_STATE_RINGING) {
736+ if (bridge == 1) {
737+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
738+ } else {
739+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
740+ }
741+ } else {
742+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
743+ }
744+ }
745+ if (bridge == 1) {
746+ if (chan->_state != AST_STATE_UP) {
747+ ast_answer(chan);
748+ }
749+ if (ast_channel_masquerade(cur, chan)) {
750+ ast_log(LOG_ERROR, "unable to masquerade\n");
751+ }
752+ ast_mutex_unlock(&cur->lock);
753+ ast_mutex_unlock(&chan->lock);
754+ } else {
755+ cur->_softhangup = AST_SOFTHANGUP_DEV;
756+ ast_mutex_unlock(&cur->lock);
757+ }
758+ } else {
759+ if(option_verbose > 2) {
760+ ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
761+ }
762+ }
763+ return res;
764+}
765+
766+static int my_pickup_channel(struct ast_channel *chan, void *data, int chanstate, int bridge) {
767+ struct ast_channel *cur;
768+ char channels[256];
769+ char evalchan[256];
770+ char *endptr;
771+ int res = -1;
772+ cur = ast_channel_walk_locked(NULL);
773+ strncpy(channels, (char *)data, sizeof(channels) - 1);
774+ while(cur) {
775+ if ((cur != chan) &&
776+ (cur->_state == chanstate)) {
777+ /* This call is a candidate (correct ringstate and not ourselves), now check if the channel is in our list */
778+ strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);
779+ /* strip the subchannel tag */
780+ endptr = strrchr(evalchan, '-');
781+ if(endptr) {
782+ *endptr = '\0';
783+ }
784+ /* check for each of the members if they match (probably a stristr will do ?) */
785+ /* if we match the code, break */
786+ if(strstr(channels, evalchan) != NULL) {
787+ ast_verbose(VERBOSE_PREFIX_1 "Nice channel, I'll take it: %s\n",evalchan);
788+ break;
789+ }
790+ }
791+ ast_mutex_unlock(&cur->lock);
792+ cur = ast_channel_walk_locked(cur);
793+ }
794+ if (cur) {
795+ if(option_verbose > 2) {
796+ if (chanstate == AST_STATE_RINGING) {
797+ if (bridge == 1) {
798+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
799+ } else {
800+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
801+ }
802+ } else {
803+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
804+ }
805+ }
806+ if (bridge == 1) {
807+ if (chan->_state != AST_STATE_UP) {
808+ ast_answer(chan);
809+ }
810+ if (ast_channel_masquerade(cur, chan)) {
811+ ast_log(LOG_ERROR, "unable to masquerade\n");
812+ }
813+ ast_mutex_unlock(&cur->lock);
814+ ast_mutex_unlock(&chan->lock);
815+ } else {
816+ cur->_softhangup = AST_SOFTHANGUP_DEV;
817+ ast_mutex_unlock(&cur->lock);
818+ }
819+ } else {
820+ if(option_verbose > 2) {
821+ ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
822+ }
823+ }
824+ return res;
825+}
826+
827+
828+static int pickup_exec(struct ast_channel *chan, void *data)
829+{
830+ int res=0;
831+ unsigned int pickupgroup=0;
832+ struct ast_module_user *u;
833+ if (!data || !strlen(data)) {
834+ pickupgroup = chan->pickupgroup;
835+ } else {
836+ pickupgroup = ast_get_group(data);
837+ }
838+ u = ast_module_user_add(chan);
839+ if (!res) {
840+ res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
841+ }
842+ if (res > 0)
843+ res = 0;
844+ ast_module_user_remove(u);
845+ return res;
846+}
847+
848+static int steal_exec(struct ast_channel *chan, void *data)
849+{
850+ int res=0;
851+ unsigned int pickupgroup=0;
852+ struct ast_module_user *u;
853+ if (!data || !strlen(data)) {
854+ pickupgroup = chan->pickupgroup;
855+ } else {
856+ pickupgroup = ast_get_group(data);
857+ }
858+ u = ast_module_user_add(chan);
859+ if (!res) {
860+ res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
861+ }
862+ if (res > 0)
863+ res = 0;
864+ ast_module_user_remove(u);
865+ return res;
866+}
867+
868+static int pickdown_exec(struct ast_channel *chan, void *data)
869+{
870+ int res=0;
871+ unsigned int pickupgroup=0;
872+ struct ast_module_user *u;
873+ if (!data || !strlen(data)) {
874+ pickupgroup = chan->pickupgroup;
875+ } else {
876+ pickupgroup = ast_get_group(data);
877+ }
878+ u = ast_module_user_add(chan);
879+ if (!res) {
880+ res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
881+ }
882+ if (res > 0)
883+ res = 0;
884+ ast_module_user_remove(u);
885+ return res;
886+}
887+
888+static int pickupchan_exec(struct ast_channel *chan, void *data) {
889+ int res=0;
890+ struct ast_module_user *u;
891+ if (!data) {
892+ ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
893+ return -1;
894+ }
895+ u = ast_module_user_add(chan);
896+ if (!res) {
897+ res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
898+ }
899+ if (res > 0)
900+ res = 0;
901+ ast_module_user_remove(u);
902+ return res;
903+}
904+
905+static int stealchan_exec(struct ast_channel *chan, void *data)
906+{
907+ int res=0;
908+ struct ast_module_user *u;
909+ if (!data) {
910+ ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
911+ return -1;
912+ }
913+
914+ u = ast_module_user_add(chan);
915+ if (!res) {
916+ res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
917+ }
918+ if (res > 0)
919+ res = 0;
920+ ast_module_user_remove(u);
921+ return res;
922+}
923+
924+
925+static int unload_module(void)
926+{
927+ ast_module_user_hangup_all();
928+ ast_unregister_application(app5);
929+ ast_unregister_application(app4);
930+ ast_unregister_application(app3);
931+ ast_unregister_application(app2);
932+ return ast_unregister_application(app);
933+}
934+
935+static int load_module(void)
936+{
937+ ast_register_application(app5, stealchan_exec, synopsis5, descrip5);
938+ ast_register_application(app4, pickupchan_exec, synopsis4, descrip4);
939+ ast_register_application(app3, pickdown_exec, synopsis3, descrip3);
940+ ast_register_application(app2, steal_exec, synopsis2, descrip2);
941+ return ast_register_application(app, pickup_exec, synopsis, descrip);
942+}
943+
944+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PickUp/PickDown/Steal/PickupChan/StealChan",
945+ .load = load_module,
946+ .unload = unload_module,
947+);
948--- /dev/null
949+++ b/apps/app_devstate.c
950@@ -0,0 +1,202 @@
951+/*
952+ * Devstate application
953+ *
954+ * Since we like the snom leds so much, a little app to
955+ * light the lights on the snom on demand ....
956+ *
957+ * Copyright (C) 2005, Druid Software
958+ *
959+ * This program is free software, distributed under the terms of
960+ * the GNU General Public License
961+ */
962+
963+#include "asterisk.h"
964+
965+#include <stdlib.h>
966+#include <unistd.h>
967+#include <string.h>
968+#include <stdio.h>
969+
970+#include "asterisk/lock.h"
971+#include "asterisk/file.h"
972+#include "asterisk/logger.h"
973+#include "asterisk/channel.h"
974+#include "asterisk/pbx.h"
975+#include "asterisk/astdb.h"
976+#include "asterisk/cli.h"
977+#include "asterisk/manager.h"
978+#include "asterisk/devicestate.h"
979+#include "asterisk/module.h"
980+
981+
982+static char type[] = "DS";
983+static char tdesc[] = "Application for sending device state messages";
984+
985+static char app[] = "Devstate";
986+
987+static char synopsis[] = "Generate a device state change event given the input parameters";
988+
989+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";
990+
991+static char devstate_cli_usage[] =
992+"Usage: devstate device state\n"
993+" Generate a device state change event given the input parameters.\n Mainly used for lighting the LEDs on the snoms.\n";
994+
995+static int devstate_cli(int fd, int argc, char *argv[]);
996+static struct ast_cli_entry cli_dev_state =
997+ { { "devstate", NULL }, devstate_cli, "Set the device state on one of the \"pseudo devices\".", devstate_cli_usage };
998+
999+
1000+static int devstate_cli(int fd, int argc, char *argv[])
1001+{
1002+ char devName[128];
1003+ if (argc != 3)
1004+ return RESULT_SHOWUSAGE;
1005+
1006+ if (ast_db_put("DEVSTATES", argv[1], argv[2]))
1007+ {
1008+ ast_log(LOG_DEBUG, "ast_db_put failed\n");
1009+ }
1010+ snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
1011+ ast_device_state_changed_literal(devName);
1012+ return RESULT_SUCCESS;
1013+}
1014+
1015+static int devstate_exec(struct ast_channel *chan, void *data)
1016+{
1017+ char *device, *state, *info;
1018+ char devName[128];
1019+ struct ast_module_user *u;
1020+
1021+
1022+ if (!(info = ast_strdupa(data))) {
1023+ ast_log(LOG_WARNING, "Unable to dupe data :(\n");
1024+ return -1;
1025+ }
1026+
1027+ u = ast_module_user_add(chan);
1028+ device = info;
1029+ state = strchr(info, '|');
1030+ if (state) {
1031+ *state = '\0';
1032+ state++;
1033+ }
1034+ else
1035+ {
1036+ ast_log(LOG_DEBUG, "No state argument supplied\n");
1037+ return -1;
1038+ }
1039+
1040+ if (ast_db_put("DEVSTATES", device, state))
1041+ {
1042+ ast_log(LOG_DEBUG, "ast_db_put failed\n");
1043+ }
1044+
1045+ snprintf(devName, sizeof(devName), "DS/%s", device);
1046+ ast_device_state_changed_literal(devName);
1047+
1048+ ast_module_user_remove(u);
1049+ return 0;
1050+}
1051+
1052+
1053+static int ds_devicestate(void *data)
1054+{
1055+ char *dest = data;
1056+ char stateStr[16];
1057+ if (ast_db_get("DEVSTATES", dest, stateStr, sizeof(stateStr)))
1058+ {
1059+ ast_log(LOG_DEBUG, "ds_devicestate couldnt get state in astdb\n");
1060+ return 0;
1061+ }
1062+ else
1063+ {
1064+ ast_log(LOG_DEBUG, "ds_devicestate dev=%s returning state %d\n",
1065+ dest, atoi(stateStr));
1066+ return (atoi(stateStr));
1067+ }
1068+}
1069+
1070+static struct ast_channel_tech devstate_tech = {
1071+ .type = type,
1072+ .description = tdesc,
1073+ .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
1074+ .devicestate = ds_devicestate,
1075+ .requester = NULL,
1076+ .send_digit_begin = NULL,
1077+ .send_digit_end = NULL,
1078+ .send_text = NULL,
1079+ .call = NULL,
1080+ .hangup = NULL,
1081+ .answer = NULL,
1082+ .read = NULL,
1083+ .write = NULL,
1084+ .bridge = NULL,
1085+ .exception = NULL,
1086+ .indicate = NULL,
1087+ .fixup = NULL,
1088+ .setoption = NULL,
1089+};
1090+
1091+static char mandescr_devstate[] =
1092+"Description: Put a value into astdb\n"
1093+"Variables: \n"
1094+" Family: ...\n"
1095+" Key: ...\n"
1096+" Value: ...\n";
1097+
1098+static int action_devstate(struct mansession *s, const struct message *m)
1099+{
1100+ const char *devstate = astman_get_header(m, "Devstate");
1101+ const char *value = astman_get_header(m, "Value");
1102+ const char *id = astman_get_header(m,"ActionID");
1103+ char devName[128];
1104+ char idText[256] = "";
1105+
1106+ if (!strlen(devstate)) {
1107+ astman_send_error(s, m, "No Devstate specified");
1108+ return 0;
1109+ }
1110+ if (!strlen(value)) {
1111+ astman_send_error(s, m, "No Value specified");
1112+ return 0;
1113+ }
1114+ if (!ast_strlen_zero(id))
1115+ snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
1116+
1117+ if (!ast_db_put("DEVSTATES", devstate, (char *)value)) {
1118+ snprintf(devName, sizeof(devName), "DS/%s", devstate);
1119+ ast_device_state_changed_literal(devName);
1120+ astman_append(s, "Response: Success\r\n%s\r\n", idText);
1121+ } else {
1122+ ast_log(LOG_DEBUG, "ast_db_put failed\n");
1123+ astman_append(s, "Response: Failed\r\n%s\r\n", idText);
1124+ }
1125+ return 0;
1126+}
1127+
1128+static int load_module(void)
1129+{
1130+ if (ast_channel_register(&devstate_tech)) {
1131+ ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
1132+ return -1;
1133+ }
1134+ ast_cli_register(&cli_dev_state);
1135+ ast_manager_register2( "Devstate", EVENT_FLAG_CALL, action_devstate, "Change a device state", mandescr_devstate );
1136+ return ast_register_application(app, devstate_exec, synopsis, descrip);
1137+}
1138+
1139+static int unload_module(void)
1140+{
1141+ int res = 0;
1142+
1143+ ast_module_user_hangup_all();
1144+ ast_manager_unregister( "Devstate");
1145+ ast_cli_unregister(&cli_dev_state);
1146+ res = ast_unregister_application(app);
1147+ ast_channel_unregister(&devstate_tech);
1148+ return res;
1149+}
1150+
1151+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Devstate Application");
1152+
1153--- /dev/null
1154+++ b/configs/watchdog.conf.sample
1155@@ -0,0 +1,22 @@
1156+;
1157+; Configuration file for res_watchdog
1158+;
1159+; type = isdnguard | watchdog
1160+; device = /dev/...
1161+; interval = interval to trigger the watchdog in ms
1162+
1163+;[ISDNguard-direct]
1164+;type = isdnguard
1165+;device = /dev/ttyS0
1166+;interval = 200
1167+
1168+;[ISDNguard-with-daemon]
1169+;type = isdnguard
1170+;device = /var/run/guard.ctl
1171+;interval = 200
1172+
1173+;[kernel_watchdog]
1174+;type = watchdog
1175+;device = /dev/watchdog
1176+;interval = 100
1177+
1178--- /dev/null
1179+++ b/res/res_watchdog.c
1180@@ -0,0 +1,137 @@
1181+/*
1182+ * Asterisk -- A telephony toolkit for Linux.
1183+ *
1184+ * Resource to make watchdogs happy
1185+ *
1186+ * Copyright (C) 2005, Junghanns.NET GmbH
1187+ *
1188+ * Klaus-Peter Junghanns <kpj@junghanns.net>
1189+ *
1190+ * This program is free software, distributed under the terms of
1191+ * the GNU General Public License
1192+ */
1193+
1194+#include "asterisk.h"
1195+#include <stdlib.h>
1196+#include <errno.h>
1197+#include <unistd.h>
1198+#include <string.h>
1199+#include <stdlib.h>
1200+#include <stdio.h>
1201+#include <sys/time.h>
1202+#include <sys/signal.h>
1203+#include <netinet/in.h>
1204+
1205+#include <asterisk/logger.h>
1206+#include <asterisk/channel.h>
1207+#include <asterisk/pbx.h>
1208+#include <asterisk/options.h>
1209+#include <asterisk/module.h>
1210+#include <asterisk/translate.h>
1211+#include <asterisk/say.h>
1212+#include <asterisk/features.h>
1213+#include <asterisk/musiconhold.h>
1214+#include <asterisk/config.h>
1215+#include <asterisk/cli.h>
1216+#include <asterisk/manager.h>
1217+#include <asterisk/utils.h>
1218+#include <asterisk/lock.h>
1219+#include <asterisk/adsi.h>
1220+
1221+static struct watchdog_pvt *watchdogs = NULL;
1222+
1223+typedef struct watchdog_pvt {
1224+ char device[80];
1225+ int fd;
1226+ int type;
1227+ int interval;
1228+ pthread_t watchdog_thread;
1229+ struct watchdog_pvt *next;
1230+} watchdog_pvt;
1231+
1232+static void *do_watchdog_thread(void *data) {
1233+ struct watchdog_pvt *woof = (struct watchdog_pvt *)data;
1234+ for (;;) {
1235+ if (woof->fd) {
1236+ write(woof->fd, "PING\n", 5);
1237+ }
1238+ usleep(woof->interval * 1000);
1239+ }
1240+ return NULL;
1241+}
1242+
1243+
1244+static int load_module(void)
1245+{
1246+ int res = 0;
1247+ const char *cat, *utype, *udevice, *uinterval;
1248+ struct ast_config *cfg;
1249+ struct watchdog_pvt *woof = NULL;
1250+
1251+ cfg = ast_config_load("watchdog.conf");
1252+ if (cfg) {
1253+ cat = ast_category_browse(cfg, NULL);
1254+ while(cat) {
1255+ cat = ast_category_browse(cfg, cat);
1256+ utype = ast_variable_retrieve(cfg, cat, "type");
1257+/* if (utype) {
1258+ ast_log(LOG_NOTICE, "type = %s\n", utype);
1259+ } */
1260+ udevice = ast_variable_retrieve(cfg, cat, "device");
1261+/* if (udevice) {
1262+ ast_log(LOG_NOTICE, "device = %s\n", udevice);
1263+ } */
1264+ uinterval = ast_variable_retrieve(cfg, cat, "interval");
1265+/* if (uinterval) {
1266+ ast_log(LOG_NOTICE, "interval = %s\n", uinterval);
1267+ } */
1268+ if (uinterval && udevice && utype) {
1269+ woof = malloc(sizeof(struct watchdog_pvt));
1270+ if (!woof) {
1271+ ast_log(LOG_ERROR, "unable to malloc!\n");
1272+ return -1;
1273+ }
1274+ memset(woof, 0x0, sizeof(struct watchdog_pvt));
1275+ strncpy(woof->device, udevice, sizeof(woof->device) - 1);
1276+
1277+ woof->interval = atoi(uinterval);;
1278+ woof->next = watchdogs;
1279+ watchdogs = woof;
1280+ woof->fd = open(woof->device, O_WRONLY | O_SYNC);
1281+ if (woof->fd) {
1282+ if (!strncmp(utype, "isdnguard", sizeof(utype))) {
1283+ woof->type = 1;
1284+ write(woof->fd, "START\n", 6);
1285+ }
1286+ ast_pthread_create(&woof->watchdog_thread, NULL, do_watchdog_thread, woof);
1287+ } else {
1288+ ast_log(LOG_WARNING, "error opening watchdog device %s !\n", woof->device);
1289+ }
1290+ }
1291+ }
1292+ ast_config_destroy(cfg);
1293+ }
1294+ return res;
1295+}
1296+
1297+
1298+static int unload_module(void)
1299+{
1300+ struct watchdog_pvt *dogs, *woof;
1301+ dogs = watchdogs;
1302+ while (dogs) {
1303+ pthread_cancel(dogs->watchdog_thread);
1304+ pthread_join(dogs->watchdog_thread, NULL);
1305+ close(dogs->fd);
1306+ woof = dogs->next;
1307+ free(dogs);
1308+ dogs = woof;
1309+ }
1310+ return 0;
1311+}
1312+
1313+
1314+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Watchdog Resource",
1315+ .load = load_module,
1316+ .unload = unload_module,
1317+);
1318--- a/main/db.c
1319+++ b/main/db.c
1320@@ -574,7 +574,7 @@ static int manager_dbget(struct mansessi
1321 astman_append(s, "Event: DBGetResponse\r\n"
1322 "Family: %s\r\n"
1323 "Key: %s\r\n"
1324- "Val: %s\r\n"
1325+ "Value: %s\r\n"
1326 "%s"
1327 "\r\n",
1328 family, key, tmp, idText);
1329@@ -582,11 +582,35 @@ static int manager_dbget(struct mansessi
1330 return 0;
1331 }
1332
1333+static int manager_dbdel(struct mansession *s, const struct message *m)
1334+{
1335+ const char *family = astman_get_header(m, "Family");
1336+ const char *key = astman_get_header(m, "Key");
1337+
1338+ if (!strlen(family)) {
1339+ astman_send_error(s, m, "No family specified");
1340+ return 0;
1341+ }
1342+ if (!strlen(key)) {
1343+ astman_send_error(s, m, "No key specified");
1344+ return 0;
1345+ }
1346+
1347+ if (ast_db_del(family, key)) {
1348+ astman_send_error(s, m, "Failed to delete entry");
1349+ } else {
1350+ astman_send_ack(s, m, "Deleted entry successfully");
1351+ }
1352+
1353+ return 0;
1354+}
1355+
1356 int astdb_init(void)
1357 {
1358 dbinit();
1359 ast_cli_register_multiple(cli_database, sizeof(cli_database) / sizeof(struct ast_cli_entry));
1360- ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
1361- ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
1362+ ast_manager_register("DBget", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
1363+ ast_manager_register("DBput", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
1364+ ast_manager_register("DBdel", EVENT_FLAG_SYSTEM, manager_dbdel, "Delete DB Entry");
1365 return 0;
1366 }
1367--- /dev/null
1368+++ b/configs/esel.conf.sample
1369@@ -0,0 +1,12 @@
1370+;
1371+; Configuration file for res_esel
1372+;
1373+
1374+;[asterisk-2]
1375+;host = 192.168.0.1
1376+;port = 5038
1377+;username = manager
1378+;secret = donkey
1379+
1380+; export the extension snom in context phones to DS/100
1381+;export => snom@phones,100
1382--- /dev/null
1383+++ b/res/res_esel.c
1384@@ -0,0 +1,384 @@
1385+/*
1386+ * Asterisk -- A telephony toolkit for Linux.
1387+ *
1388+ * Extension State Export Logic (E.S.E.L) (Sorry, i couldnt resist...)
1389+ *
1390+ * Resource to export extension states to other Asterisk servers
1391+ *
1392+ * Copyright (C) 2006, Junghanns.NET GmbH
1393+ *
1394+ * Klaus-Peter Junghanns <kpj@junghanns.net>
1395+ *
1396+ * This program is free software, distributed under the terms of
1397+ * the GNU General Public License
1398+ */
1399+
1400+#include "asterisk.h"
1401+
1402+#include <stdlib.h>
1403+#include <errno.h>
1404+#include <unistd.h>
1405+#include <string.h>
1406+#include <stdlib.h>
1407+#include <stdio.h>
1408+#include <sys/time.h>
1409+#include <sys/signal.h>
1410+#include <netinet/in.h>
1411+#include <sys/types.h>
1412+#include <sys/socket.h>
1413+
1414+#include "asterisk/file.h"
1415+#include "asterisk/logger.h"
1416+#include "asterisk/channel.h"
1417+#include "asterisk/pbx.h"
1418+#include "asterisk/options.h"
1419+#include "asterisk/module.h"
1420+#include "asterisk/translate.h"
1421+#include "asterisk/say.h"
1422+#include "asterisk/features.h"
1423+#include "asterisk/musiconhold.h"
1424+#include "asterisk/config.h"
1425+#include "asterisk/cli.h"
1426+#include "asterisk/manager.h"
1427+#include "asterisk/utils.h"
1428+#include "asterisk/lock.h"
1429+#include "asterisk/adsi.h"
1430+
1431+
1432+AST_MUTEX_DEFINE_STATIC(listlock);
1433+
1434+typedef struct esel_extension_state {
1435+ char context[AST_MAX_EXTENSION];
1436+ char exten[AST_MAX_EXTENSION];
1437+ int state;
1438+ char devstate[AST_MAX_EXTENSION];
1439+ struct esel_extension_state *next;
1440+ struct esel_extension_state *prev;
1441+} esel_extension_state;
1442+
1443+typedef struct esel_export {
1444+ char context[AST_MAX_EXTENSION];
1445+ char exten[AST_MAX_EXTENSION];
1446+ char devstate[AST_MAX_EXTENSION];
1447+ struct esel_export *next;
1448+} esel_export;
1449+
1450+typedef struct esel_queue {
1451+ struct esel_extension_state *head;
1452+ struct esel_extension_state *tail;
1453+ int count;
1454+ ast_cond_t cond;
1455+ ast_mutex_t lock;
1456+} esel_queue;
1457+
1458+typedef struct esel_pvt {
1459+ char name[80];
1460+ char username[80];
1461+ char secret[80];
1462+ char host[80];
1463+ int port;
1464+ struct sockaddr_in raddr;
1465+ int sockfd;
1466+ int connected;
1467+ pthread_t esel_thread;
1468+
1469+ /* list of extensions to export */
1470+ struct esel_export *extensions;
1471+
1472+ /* queue */
1473+ struct esel_queue queue;
1474+
1475+ struct esel_pvt *next;
1476+} esel_pvt;
1477+
1478+static struct esel_pvt *donkeys = NULL;
1479+
1480+static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data) {
1481+ struct esel_extension_state *exstate = NULL;
1482+
1483+ exstate = malloc(sizeof(struct esel_extension_state));
1484+ if (!exstate) {
1485+ ast_log(LOG_ERROR, "Unable to malloc!\n");
1486+ return 1;
1487+ }
1488+ memset(exstate,0,sizeof(struct esel_extension_state));
1489+ exstate->next = NULL;
1490+ exstate->prev = NULL;
1491+
1492+ ast_mutex_lock(&queue->lock);
1493+ if (queue->count > 100) {
1494+ ast_mutex_unlock(&queue->lock);
1495+ free(exstate);
1496+ if (option_verbose > 5)
1497+ ast_log(LOG_WARNING, "E.S.E.L Queue too long.\n");
1498+ return -1;
1499+ }
1500+ ast_copy_string(exstate->exten, exten, sizeof(exstate->exten));
1501+ ast_copy_string(exstate->context, context, sizeof(exstate->context));
1502+ exstate->state = state;
1503+ if (!queue->head) {
1504+ /* Empty queue */
1505+ queue->head = exstate;
1506+ queue->tail = exstate;
1507+ } else {
1508+ /* Double link */
1509+ queue->tail->next = exstate;
1510+ exstate->prev = queue->tail;
1511+ queue->tail = exstate;
1512+ }
1513+ queue->count++;
1514+ ast_cond_signal(&queue->cond);
1515+ ast_mutex_unlock(&queue->lock);
1516+ return 0;
1517+}
1518+
1519+static int esel_is_exported(struct esel_export *extensions, struct esel_extension_state *exstate) {
1520+ struct esel_export *export = NULL;
1521+ export = extensions;
1522+ while (export) {
1523+ if ((!strcasecmp(export->exten, exstate->exten)) && (!strcasecmp(export->context, exstate->context))) {
1524+ /* copy mapping */
1525+ ast_copy_string(exstate->devstate, export->devstate, sizeof(exstate->devstate));
1526+ return 1;
1527+ }
1528+ export = export->next;
1529+ }
1530+ return 0;
1531+}
1532+
1533+static int esel_state2devstate(int state) {
1534+ switch(state) {
1535+ case 1:
1536+ return 2;
1537+ case 8:
1538+ return 6;
1539+ default:
1540+ return state;
1541+ }
1542+}
1543+
1544+static void esel_export_to_remote(struct esel_extension_state *exstate, struct esel_pvt *esel) {
1545+ char msg[1024];
1546+ int sent = 0;
1547+ memset(msg, 0x0, sizeof(msg));
1548+ snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state));
1549+ sent = send(esel->sockfd, msg, strlen(msg), 0);
1550+ if (sent == -1) {
1551+ esel->connected = 0;
1552+ }
1553+// ast_log(LOG_NOTICE, "%s", msg);
1554+}
1555+
1556+static void *do_esel_thread(void *data) {
1557+ struct esel_pvt *esel = (struct esel_pvt *)data;
1558+ struct esel_queue *queue = &esel->queue;
1559+ struct esel_extension_state *exstate = NULL;
1560+ char msg[1024];
1561+ char buf[1024];
1562+ int numbytes = 0;
1563+ int sent = 0;
1564+ int res = 0;
1565+ for (;;) {
1566+ if (esel->connected) {
1567+ ast_mutex_lock(&queue->lock);
1568+ if (queue->count == 0)
1569+ ast_cond_wait(&queue->cond, &queue->lock);
1570+ exstate = queue->head;
1571+ if (exstate) {
1572+ if (exstate->next) {
1573+ queue->head = exstate->next;
1574+ } else {
1575+ queue->head = NULL;
1576+ queue->tail = NULL;
1577+ }
1578+ queue->count--;
1579+ } else {
1580+ ast_log(LOG_ERROR, "I SHOULD NEVER HAPPEN! EXPECT SOME MAJOR KABOOM! DUCK AND COVER!\n");
1581+ }
1582+ ast_mutex_unlock(&queue->lock);
1583+
1584+ if (exstate) {
1585+ if (esel_is_exported(esel->extensions, exstate)) {
1586+ esel_export_to_remote(exstate, esel);
1587+ }
1588+ free(exstate);
1589+ exstate = NULL;
1590+ }
1591+ } else {
1592+ if (esel->sockfd > 0)
1593+ close(esel->sockfd);
1594+ if ((esel->sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
1595+ ast_log(LOG_ERROR, "unable to request socket!\n");
1596+ return NULL;
1597+ }
1598+ /* try to connect */
1599+ res = connect(esel->sockfd, (struct sockaddr *)&esel->raddr, sizeof(struct sockaddr));
1600+ if (res) {
1601+ ast_log(LOG_NOTICE, "error connecting to %s:%d\n", esel->host, esel->port);
1602+ } else {
1603+ while (strncasecmp(buf, "Asterisk Call Manager:", 21)) {
1604+ if ((numbytes=recv(esel->sockfd, buf, sizeof(buf), 0)) == -1) {
1605+ esel->connected = 0;
1606+ continue;
1607+ }
1608+ buf[numbytes] = '\0';
1609+ // ast_log(LOG_NOTICE, "read: %s", buf);
1610+ }
1611+ /* log into remote manager */
1612+ memset(msg, 0x0, sizeof(msg));
1613+ snprintf(msg, sizeof(msg) - 1, "Action: Login\r\nUsername: %s\r\nSecret: %s\r\n\r\n", esel->username, esel->secret);
1614+ sent = send(esel->sockfd, msg, strlen(msg), 0);
1615+
1616+ while (strncasecmp(buf, "Response:", 9)) {
1617+ if ((numbytes=recv(esel->sockfd, buf, sizeof(buf), 0)) == -1) {
1618+ continue;
1619+ }
1620+ buf[numbytes] = '\0';
1621+ // ast_log(LOG_NOTICE, "read: %s", buf);
1622+ }
1623+
1624+ if (!strncasecmp(buf, "Response: Success", 17)) {
1625+ esel->connected = 1;
1626+ } else {
1627+ ast_log(LOG_ERROR, "error login into remote asterisk %s\n", esel->name);
1628+ }
1629+ }
1630+ /* time heals everything... */
1631+ sleep(10);
1632+ }
1633+ }
1634+ return NULL;
1635+}
1636+
1637+static int esel_state_cb(char *context, char *exten, int state, void *data) {
1638+ struct esel_pvt *esel;
1639+
1640+ esel = donkeys;
1641+ ast_mutex_lock(&listlock);
1642+ while (esel) {
1643+ esel_queue_extension_state(&esel->queue, context, exten, state, data);
1644+ esel = esel->next;
1645+ }
1646+ ast_mutex_unlock(&listlock);
1647+ return 0;
1648+}
1649+
1650+
1651+static int load_module(void)
1652+{
1653+ int res = 0;
1654+ const char *cat, *host, *port, *username, *secret, *name;
1655+ struct ast_config *cfg;
1656+ struct ast_variable *var;
1657+ struct esel_pvt *esel = NULL;
1658+ struct esel_export *export = NULL;
1659+ struct hostent *he;
1660+ struct ast_hostent h;
1661+
1662+ cfg = ast_config_load("esel.conf");
1663+ if (cfg) {
1664+ cat = ast_category_browse(cfg, NULL);
1665+ while(cat) {
1666+ name = cat;
1667+ host = ast_variable_retrieve(cfg, cat, "host");
1668+ username = ast_variable_retrieve(cfg, cat, "username");
1669+ secret = ast_variable_retrieve(cfg, cat, "secret");
1670+ port = ast_variable_retrieve(cfg, cat, "port");
1671+
1672+ if (name && host && username && secret && port) {
1673+ esel = malloc(sizeof(struct esel_pvt));
1674+ if (!esel) {
1675+ ast_log(LOG_ERROR, "unable to malloc!\n");
1676+ return -1;
1677+ }
1678+ memset(esel, 0x0, sizeof(struct esel_pvt));
1679+ ast_copy_string(esel->name, name, sizeof(esel->name));
1680+ ast_copy_string(esel->host, host, sizeof(esel->host));
1681+ ast_copy_string(esel->username, username, sizeof(esel->username));
1682+ ast_copy_string(esel->secret, secret, sizeof(esel->secret));
1683+
1684+ esel->port = atoi(port);
1685+ if ((he=ast_gethostbyname(host, &h)) == NULL) {
1686+ ast_log(LOG_ERROR, "unknown host!\n");
1687+ return -1;
1688+ }
1689+
1690+ esel->raddr.sin_family = AF_INET;
1691+ esel->raddr.sin_port = htons(esel->port);
1692+ esel->raddr.sin_addr = *((struct in_addr *)he->h_addr);
1693+ bzero(&(esel->raddr.sin_zero), 8);
1694+
1695+ esel->connected = 0;
1696+
1697+ ast_mutex_init(&esel->queue.lock);
1698+ ast_cond_init(&esel->queue.cond, NULL);
1699+
1700+
1701+ /* read exports */
1702+ var = ast_variable_browse(cfg, cat);
1703+ while (var) {
1704+ if (!strcasecmp(var->name, "export")) {
1705+ char *extenp = NULL, *contextp = NULL, *devstatep = NULL;
1706+ extenp = var->value;
1707+ devstatep = strchr(var->value, ',') + 1;
1708+ contextp = strchr(var->value, '@') + 1;
1709+ if (devstatep && contextp) {
1710+ export = malloc(sizeof(struct esel_export));
1711+ if (!export) {
1712+ ast_log(LOG_ERROR, "unable to malloc!\n");
1713+ return -1;
1714+ }
1715+ memset(export, 0x0, sizeof(struct esel_export));
1716+ ast_copy_string(export->exten, extenp, contextp - extenp);
1717+ ast_copy_string(export->context, contextp, devstatep - contextp);
1718+ ast_copy_string(export->devstate, devstatep, sizeof(export->devstate));
1719+ if (option_verbose > 2)
1720+ ast_verbose(VERBOSE_PREFIX_3 "exporting %s @ %s as %s to %s\n", export->exten, export->context , export->devstate , esel->name);
1721+ export->next = esel->extensions;
1722+ esel->extensions = export;
1723+ export = NULL;
1724+ }
1725+ }
1726+ var = var->next;
1727+ }
1728+
1729+
1730+
1731+ esel->next = donkeys;
1732+ donkeys = esel;
1733+
1734+ ast_pthread_create(&esel->esel_thread, NULL, do_esel_thread, esel);
1735+
1736+ }
1737+ cat = ast_category_browse(cfg, cat);
1738+ }
1739+ ast_config_destroy(cfg);
1740+ }
1741+ ast_extension_state_add(NULL, NULL, esel_state_cb, NULL);
1742+ return res;
1743+}
1744+
1745+
1746+static int unload_module(void)
1747+{
1748+ struct esel_pvt *esel, *eseln;
1749+ ast_module_user_hangup_all();
1750+ esel = donkeys;
1751+ ast_mutex_lock(&listlock);
1752+ while (esel) {
1753+ pthread_cancel(esel->esel_thread);
1754+ pthread_join(esel->esel_thread, NULL);
1755+ ast_mutex_destroy(&esel->queue.lock);
1756+ close(esel->sockfd);
1757+ eseln = esel->next;
1758+ free(esel);
1759+ esel = eseln;
1760+ }
1761+ ast_mutex_unlock(&listlock);
1762+ return 0;
1763+}
1764+
1765+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Extension State Export Logic (E.S.E.L.) Resource",
1766+ .load = load_module,
1767+ .unload = unload_module,
1768+);
1769--- a/channels/chan_iax2.c
1770+++ b/channels/chan_iax2.c
1771@@ -11,6 +11,9 @@
1772 * the project provides a web site, mailing lists and IRC
1773 * channels for your use.
1774 *
1775+ * Hangup cause signalling implementation by
1776+ * Levent Guendogdu <levon@feature-it.com>
1777+ *
1778 * This program is free software, distributed under the terms of
1779 * the GNU General Public License Version 2. See the LICENSE file
1780 * at the top of the source tree.
1781@@ -3362,7 +3365,7 @@ static int iax2_hangup(struct ast_channe
1782 ast_mutex_lock(&iaxsl[callno]);
1783 if (callno && iaxs[callno]) {
1784 if (option_debug)
1785- ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
1786+ ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
1787 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
1788 /* Send the hangup unless we have had a transmission error or are already gone */
1789 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
1790@@ -3416,7 +3419,8 @@ static int iax2_setoption(struct ast_cha
1791
1792 static struct ast_frame *iax2_read(struct ast_channel *c)
1793 {
1794- ast_log(LOG_NOTICE, "I should never be called!\n");
1795+ if (option_verbose > 3)
1796+ ast_log(LOG_NOTICE, "I should never be called!\n");
1797 return &ast_null_frame;
1798 }
1799
1800--- a/apps/app_zapras.c
1801+++ b/apps/app_zapras.c
1802@@ -183,7 +183,7 @@ static void run_ras(struct ast_channel *
1803 }
1804 }
1805 /* Throw back into audio mode */
1806- x = 1;
1807+ x = 0;
1808 ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
1809
1810 /* Restore saved values */
1811--- a/main/channel.c
1812+++ b/main/channel.c
1813@@ -3898,6 +3898,10 @@ enum ast_bridge_result ast_channel_bridg
1814 c1->name, c1->_bridge->name);
1815 return -1;
1816 }
1817+
1818+ if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
1819+ config->flags = 0;
1820+ }
1821
1822 /* Stop if we're a zombie or need a soft hangup */
1823 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
1824--- a/apps/app_meetme.c
1825+++ b/apps/app_meetme.c
1826@@ -1405,8 +1405,9 @@ static int conf_run(struct ast_channel *
1827 char members[10] = "";
1828 int dtmf, opt_waitmarked_timeout = 0;
1829 time_t timeout = 0;
1830+ int dyna_buff = CONF_SIZE;
1831 ZT_BUFFERINFO bi;
1832- char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
1833+ char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET];
1834 char *buf = __buf + AST_FRIENDLY_OFFSET;
1835 int setusercount = 0;
1836
1837@@ -1615,7 +1616,7 @@ static int conf_run(struct ast_channel *
1838 }
1839 /* Setup buffering information */
1840 memset(&bi, 0, sizeof(bi));
1841- bi.bufsize = CONF_SIZE/2;
1842+ bi.bufsize = dyna_buff / 2;
1843 bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
1844 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
1845 bi.numbufs = audio_buffers;
1846@@ -1926,6 +1927,14 @@ static int conf_run(struct ast_channel *
1847 f = ast_read(c);
1848 if (!f)
1849 break;
1850+ if (f->datalen && f->datalen != dyna_buff) {
1851+ ast_log(LOG_NOTICE, "Audio bytes: %d Buffer size: %d\n", f->datalen, dyna_buff);
1852+ if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */
1853+ dyna_buff = f->datalen;
1854+ close(fd);
1855+ goto zapretry;
1856+ }
1857+ }
1858 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
1859 if (user->talk.actual)
1860 ast_frame_adjust_volume(f, user->talk.actual);
1861Answer the channel before saying things (SayNumber, SayDigits,
1862SayCharacters, SayPhonetic).
1863
1864--- a/main/pbx.c
1865+++ b/main/pbx.c
1866@@ -6076,6 +6076,9 @@ static int pbx_builtin_saynumber(struct
1867 return -1;
1868 }
1869 }
1870+ if (chan->_state != AST_STATE_UP) {
1871+ ast_answer(chan);
1872+ }
1873
1874 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
1875 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
1876@@ -6088,8 +6091,12 @@ static int pbx_builtin_saydigits(struct
1877 {
1878 int res = 0;
1879
1880- if (data)
1881+ if (data) {
1882+ if (chan->_state != AST_STATE_UP) {
1883+ ast_answer(chan);
1884+ }
1885 res = ast_say_digit_str(chan, data, "", chan->language);
1886+ }
1887 return res;
1888 }
1889
1890@@ -6097,8 +6104,12 @@ static int pbx_builtin_saycharacters(str
1891 {
1892 int res = 0;
1893
1894- if (data)
1895+ if (data) {
1896+ if (chan->_state != AST_STATE_UP) {
1897+ ast_answer(chan);
1898+ }
1899 res = ast_say_character_str(chan, data, "", chan->language);
1900+ }
1901 return res;
1902 }
1903
1904@@ -6106,8 +6117,12 @@ static int pbx_builtin_sayphonetic(struc
1905 {
1906 int res = 0;
1907
1908- if (data)
1909+ if (data) {
1910+ if (chan->_state != AST_STATE_UP) {
1911+ ast_answer(chan);
1912+ }
1913 res = ast_say_phonetic_str(chan, data, "", chan->language);
1914+ }
1915 return res;
1916 }
1917
1918--- a/apps/app_dial.c
1919+++ b/apps/app_dial.c
1920@@ -11,6 +11,10 @@
1921 * the project provides a web site, mailing lists and IRC
1922 * channels for your use.
1923 *
1924+ * Copyright (C) 2004, Junghanns.NET GmbH
1925+ *
1926+ * Klaus-Peter Junghanns <kpj@junghanns.net>
1927+ *
1928 * This program is free software, distributed under the terms of
1929 * the GNU General Public License Version 2. See the LICENSE file
1930 * at the top of the source tree.
1931@@ -130,7 +134,8 @@ static char *descrip =
1932 " H - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
1933 " i - Asterisk will ignore any forwarding requests it may receive on this\n"
1934 " dial attempt.\n"
1935-" j - Jump to priority n+101 if all of the requested channels were busy.\n"
1936+" j - Jump to priority n+101 if the called party was busy.\n"
1937+" Jump to priority n+201 if all of the requested channels were busy.\n"
1938 " k - Allow the called party to enable parking of the call by sending\n"
1939 " the DTMF sequence defined for call parking in features.conf.\n"
1940 " K - Allow the calling party to enable parking of the call by sending\n"
1941@@ -1292,14 +1297,16 @@ static int dial_exec_full(struct ast_cha
1942 }
1943
1944 if (!outgoing) {
1945- strcpy(status, "CHANUNAVAIL");
1946+ ast_copy_string(status, "CHANUNAVAIL", sizeof(status));
1947 if(fulldial == num_dialed) {
1948 res = -1;
1949 goto out;
1950 }
1951+ /* See if there is a special message */
1952+ ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1953 } else {
1954 /* Our status will at least be NOANSWER */
1955- strcpy(status, "NOANSWER");
1956+ ast_copy_string(status, "NOANSWER", sizeof(status));
1957 if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
1958 moh = 1;
1959 if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
1960--- a/apps/app_dial.c
1961+++ b/apps/app_dial.c
1962@@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
1963 #include "asterisk/privacy.h"
1964 #include "asterisk/stringfields.h"
1965 #include "asterisk/global_datastores.h"
1966+#include "asterisk/transcap.h"
1967
1968 static char *app = "Dial";
1969
1970@@ -1652,23 +1653,25 @@ static int dial_exec_full(struct ast_cha
1971 ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
1972 if (play_to_callee)
1973 ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
1974- if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1975+ if ((chan->transfercapability != AST_TRANS_CAP_DIGITAL) && (chan->transfercapability != AST_TRANS_CAP_RESTRICTED_DIGITAL)) {
1976+ /* only non-digital calls are allowed to go through userspace */
1977+ if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1978 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1979- if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1980+ if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1981 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1982- if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1983+ if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1984 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1985- if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1986+ if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1987 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1988- if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1989+ if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1990 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1991- if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
1992+ if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
1993 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1994- if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
1995+ if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
1996 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
1997- if (ast_test_flag(peerflags, OPT_CALLER_PARK))
1998+ if (ast_test_flag(peerflags, OPT_CALLER_PARK))
1999 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2000-
2001+ }
2002 config.timelimit = timelimit;
2003 config.play_warning = play_warning;
2004 config.warning_freq = warning_freq;
2005--- a/apps/app_dial.c
2006+++ b/apps/app_dial.c
2007@@ -198,6 +198,8 @@ static char *descrip =
2008 " family/key is not specified.\n"
2009 " r - Indicate ringing to the calling party. Pass no audio to the calling\n"
2010 " party until the called channel has answered.\n"
2011+" R - indicate ringing to the calling party when the called party indicates\n"
2012+" ringing, pass no audio until answered.\n"
2013 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
2014 " answered the call.\n"
2015 " t - Allow the called party to transfer the calling party by sending the\n"
2016@@ -254,6 +256,7 @@ enum {
2017 OPT_CALLEE_PARK = (1 << 25),
2018 OPT_CALLER_PARK = (1 << 26),
2019 OPT_IGNORE_FORWARDING = (1 << 27),
2020+ OPT_NOINBAND = (1 << 28),
2021 } dial_exec_option_flags;
2022
2023 #define DIAL_STILLGOING (1 << 30)
2024@@ -297,6 +300,7 @@ AST_APP_OPTIONS(dial_exec_options, {
2025 AST_APP_OPTION('p', OPT_SCREENING),
2026 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
2027 AST_APP_OPTION('r', OPT_RINGBACK),
2028+ AST_APP_OPTION('R', OPT_NOINBAND),
2029 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
2030 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
2031 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
2032@@ -412,7 +416,7 @@ static struct ast_channel *wait_for_answ
2033 int orig = *to;
2034 struct ast_channel *peer = NULL;
2035 /* single is set if only one destination is enabled */
2036- int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
2037+ int single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_NOINBAND));
2038
2039 if (single) {
2040 /* Turn off hold music, etc */
2041@@ -633,7 +637,7 @@ static struct ast_channel *wait_for_answ
2042 /* Setup early media if appropriate */
2043 if (single && CAN_EARLY_BRIDGE(peerflags))
2044 ast_rtp_early_bridge(in, c);
2045- if (!ast_test_flag(outgoing, OPT_RINGBACK))
2046+ if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_NOINBAND))
2047 ast_indicate(in, AST_CONTROL_PROGRESS);
2048 break;
2049 case AST_CONTROL_VIDUPDATE:
2050@@ -651,7 +655,7 @@ static struct ast_channel *wait_for_answ
2051 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name);
2052 if (single && CAN_EARLY_BRIDGE(peerflags))
2053 ast_rtp_early_bridge(in, c);
2054- if (!ast_test_flag(outgoing, OPT_RINGBACK))
2055+ if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_NOINBAND))
2056 ast_indicate(in, AST_CONTROL_PROCEEDING);
2057 break;
2058 case AST_CONTROL_HOLD:
2059@@ -669,7 +673,7 @@ static struct ast_channel *wait_for_answ
2060 /* Ignore going off hook and flash */
2061 break;
2062 case -1:
2063- if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
2064+ if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK | OPT_NOINBAND)) {
2065 if (option_verbose > 2)
2066 ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name);
2067 ast_indicate(in, -1);
2068@@ -1091,7 +1095,7 @@ static int dial_exec_full(struct ast_cha
2069 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
2070 }
2071
2072- ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
2073+ ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_NOINBAND);
2074 /* loop through the list of dial destinations */
2075 rest = args.peers;
2076 while ((cur = strsep(&rest, "&")) ) {
2077@@ -1116,7 +1120,7 @@ static int dial_exec_full(struct ast_cha
2078 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
2079 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
2080 OPT_CALLEE_PARK | OPT_CALLER_PARK |
2081- OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
2082+ OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID | OPT_NOINBAND);
2083 ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);
2084 }
2085 ast_copy_string(numsubst, number, sizeof(numsubst));
2086@@ -1319,7 +1323,7 @@ static int dial_exec_full(struct ast_cha
2087 ast_moh_start(chan, NULL, NULL);
2088 }
2089 ast_indicate(chan, AST_CONTROL_PROGRESS);
2090- } else if (ast_test_flag(outgoing, OPT_RINGBACK)) {
2091+ } else if (ast_test_flag(outgoing, OPT_RINGBACK | OPT_NOINBAND)) {
2092 ast_indicate(chan, AST_CONTROL_RINGING);
2093 sentringing++;
2094 }
2095@@ -1442,7 +1446,7 @@ static int dial_exec_full(struct ast_cha
2096
2097 if (ast_test_flag(&opts, OPT_MUSICBACK)) {
2098 ast_moh_stop(chan);
2099- } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
2100+ } else if (ast_test_flag(&opts, OPT_RINGBACK | OPT_NOINBAND)) {
2101 ast_indicate(chan, -1);
2102 sentringing=0;
2103 }
2104--- a/apps/app_dial.c
2105+++ b/apps/app_dial.c
2106@@ -201,7 +201,8 @@ static char *descrip =
2107 " R - indicate ringing to the calling party when the called party indicates\n"
2108 " ringing, pass no audio until answered.\n"
2109 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
2110-" answered the call.\n"
2111+" answered the call.\n"
2112+" c - callback initiation, ring once and hangup.\n"
2113 " t - Allow the called party to transfer the calling party by sending the\n"
2114 " DTMF sequence defined in features.conf.\n"
2115 " T - Allow the calling party to transfer the called party by sending the\n"
2116@@ -257,6 +258,7 @@ enum {
2117 OPT_CALLER_PARK = (1 << 26),
2118 OPT_IGNORE_FORWARDING = (1 << 27),
2119 OPT_NOINBAND = (1 << 28),
2120+ OPT_CALLBACK_INIT = (1 << 29),
2121 } dial_exec_option_flags;
2122
2123 #define DIAL_STILLGOING (1 << 30)
2124@@ -301,6 +303,7 @@ AST_APP_OPTIONS(dial_exec_options, {
2125 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
2126 AST_APP_OPTION('r', OPT_RINGBACK),
2127 AST_APP_OPTION('R', OPT_NOINBAND),
2128+ AST_APP_OPTION('c', OPT_CALLBACK_INIT),
2129 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
2130 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
2131 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
2132@@ -621,14 +624,20 @@ static struct ast_channel *wait_for_answ
2133 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
2134 break;
2135 case AST_CONTROL_RINGING:
2136- if (option_verbose > 2)
2137+ if (ast_test_flag(peerflags, OPT_CALLBACK_INIT)) {
2138+ if (option_verbose > 2)
2139+ ast_verbose( VERBOSE_PREFIX_3 "%s is ringing, hanging up.\n", o->chan->name);
2140+ return NULL;
2141+ } else {
2142+ if (option_verbose > 2)
2143 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name);
2144- /* Setup early media if appropriate */
2145- if (single && CAN_EARLY_BRIDGE(peerflags))
2146+ /* Setup early media if appropriate */
2147+ if (single && CAN_EARLY_BRIDGE(peerflags))
2148 ast_rtp_early_bridge(in, c);
2149- if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
2150+ if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
2151 ast_indicate(in, AST_CONTROL_RINGING);
2152 (*sentringing)++;
2153+ }
2154 }
2155 break;
2156 case AST_CONTROL_PROGRESS:
2157@@ -1095,7 +1104,7 @@ static int dial_exec_full(struct ast_cha
2158 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
2159 }
2160
2161- ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_NOINBAND);
2162+ ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_CALLBACK_INIT | OPT_NOINBAND);
2163 /* loop through the list of dial destinations */
2164 rest = args.peers;
2165 while ((cur = strsep(&rest, "&")) ) {
2166# Allow as many spans as Zaptel can take (defualt: 128).
2167# There is a static array of zt_pris allocated at this size.
2168# For that reason upstream only sort-of merged it: made it a
2169# compile-time option in 1.6 .
2170
2171--- a/channels/chan_zap.c
2172+++ b/channels/chan_zap.c
2173@@ -190,7 +190,7 @@ static const char config[] = "zapata.con
2174 #define SIG_GR303FXOKS (0x0100000 | ZT_SIG_FXOKS)
2175 #define SIG_GR303FXSKS (0x0100000 | ZT_SIG_FXSKS)
2176
2177-#define NUM_SPANS 32
2178+#define NUM_SPANS ZT_MAX_SPANS
2179 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
2180 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
2181
2182--- a/include/asterisk/channel.h
2183+++ b/include/asterisk/channel.h
2184@@ -435,6 +435,7 @@ struct ast_channel {
2185 unsigned int flags; /*!< channel flags of AST_FLAG_ type */
2186 unsigned short transfercapability; /*!< ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
2187 AST_LIST_HEAD_NOLOCK(, ast_frame) readq;
2188+ char lowlayercompat[16]; /*!< ISDN Low Layer Compatibility */
2189 int alertpipe[2];
2190
2191 int nativeformats; /*!< Kinds of data this channel can natively handle */
2192--- a/channels/chan_zap.c
2193+++ b/channels/chan_zap.c
2194@@ -11,6 +11,10 @@
2195 * the project provides a web site, mailing lists and IRC
2196 * channels for your use.
2197 *
2198+ * Copyright (C) 2003-2006 Junghanns.NET GmbH
2199+ * Klaus-Peter Junghanns <kpj@junghanns.net>
2200+ *
2201+ *
2202 * This program is free software, distributed under the terms of
2203 * the GNU General Public License Version 2. See the LICENSE file
2204 * at the top of the source tree.
2205@@ -216,8 +220,6 @@ static struct ast_channel inuse;
2206 #ifdef PRI_GETSET_TIMERS
2207 static int pritimers[PRI_MAX_TIMERS];
2208 #endif
2209-static int pridebugfd = -1;
2210-static char pridebugfilename[1024] = "";
2211 #endif
2212
2213 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
2214@@ -235,10 +237,6 @@ AST_MUTEX_DEFINE_STATIC(iflock);
2215
2216 static int ifcount = 0;
2217
2218-#ifdef HAVE_PRI
2219-AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
2220-#endif
2221-
2222 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
2223 when it's doing something critical. */
2224 AST_MUTEX_DEFINE_STATIC(monlock);
2225@@ -253,6 +251,7 @@ static enum ast_bridge_result zt_bridge(
2226
2227 static int zt_sendtext(struct ast_channel *c, const char *text);
2228
2229+
2230 /*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
2231 static inline int zt_get_event(int fd)
2232 {
2233@@ -297,6 +296,14 @@ static int ringt_base = DEFAULT_RINGT;
2234 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
2235 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
2236
2237+struct zt_suspended_call {
2238+ ast_mutex_t lock; /* Mutex */
2239+ char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
2240+ char callid[10]; /* the callID provided by the user */
2241+ int parked_at; /* extension in the call parking context */
2242+ struct zt_suspended_call *next;
2243+};
2244+
2245 struct zt_pri {
2246 pthread_t master; /*!< Thread of master */
2247 ast_mutex_t lock; /*!< Mutex */
2248@@ -310,6 +317,8 @@ struct zt_pri {
2249 int nsf; /*!< Network-Specific Facilities */
2250 int dialplan; /*!< Dialing plan */
2251 int localdialplan; /*!< Local dialing plan */
2252+ char nocid[AST_MAX_EXTENSION]; /*!< CallerID string to use if none provided */
2253+ char withheldcid[AST_MAX_EXTENSION]; /*!< CallerID string to use if CallerID is withheld */
2254 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
2255 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
2256 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
2257@@ -321,6 +330,7 @@ struct zt_pri {
2258 int prilogicalspan; /*!< Logical span number within trunk group */
2259 int numchans; /*!< Num of channels we represent */
2260 int overlapdial; /*!< In overlap dialing mode */
2261+ int usercid;
2262 int facilityenable; /*!< Enable facility IEs */
2263 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
2264 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
2265@@ -336,6 +346,8 @@ struct zt_pri {
2266 struct zt_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
2267 struct zt_pvt *crvs; /*!< Member CRV structs */
2268 struct zt_pvt *crvend; /*!< Pointer to end of CRV structs */
2269+ struct zt_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
2270+ int debugfd;
2271 };
2272
2273
2274@@ -453,6 +465,8 @@ static struct zt_pvt {
2275 unsigned int echocanbridged:1;
2276 unsigned int echocanon:1;
2277 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
2278+ /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
2279+ on a zap channel with EC to be off no matter what happens. */
2280 unsigned int firstradio:1;
2281 unsigned int hanguponpolarityswitch:1;
2282 unsigned int hardwaredtmf:1;
2283@@ -467,7 +481,8 @@ static struct zt_pvt {
2284 unsigned int overlapdial:1;
2285 unsigned int permcallwaiting:1;
2286 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
2287- unsigned int priindication_oob:1;
2288+ unsigned int priindication_oob:2;
2289+ unsigned int pritransfer:2;
2290 unsigned int priexclusive:1;
2291 unsigned int pulse:1;
2292 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
2293@@ -504,6 +519,7 @@ static struct zt_pvt {
2294 #endif
2295 char cid_num[AST_MAX_EXTENSION];
2296 int cid_ton; /*!< Type Of Number (TON) */
2297+ int cid_pres; /*!< Calling Presentation */
2298 char cid_name[AST_MAX_EXTENSION];
2299 char lastcid_num[AST_MAX_EXTENSION];
2300 char lastcid_name[AST_MAX_EXTENSION];
2301@@ -569,6 +585,8 @@ static struct zt_pvt {
2302 struct zt_pvt *bearer;
2303 struct zt_pvt *realcall;
2304 q931_call *call;
2305+ int tei; /* channel in use by this tei */
2306+ q931_call *holdedcall;
2307 int prioffset;
2308 int logicalspan;
2309 #endif
2310@@ -614,11 +632,14 @@ static struct zt_chan_conf zt_chan_conf_
2311 .minunused = 2,
2312 .idleext = "",
2313 .idledial = "",
2314+ .nocid = "No CID available",
2315+ .withheldcid = "CID withheld",
2316 .internationalprefix = "",
2317 .nationalprefix = "",
2318 .localprefix = "",
2319 .privateprefix = "",
2320 .unknownprefix = "",
2321+ .usercid = 0,
2322
2323 .resetinterval = 3600
2324 },
2325@@ -630,6 +651,8 @@ static struct zt_chan_conf zt_chan_conf_
2326 .mohinterpret = "default",
2327 .mohsuggest = "",
2328 .transfertobusy = 1,
2329+ .priindication_oob = 0,
2330+ .pritransfer = 0,
2331
2332 .cid_signalling = CID_SIG_BELL,
2333 .cid_start = CID_START_RING,
2334@@ -684,6 +707,8 @@ static int zt_indicate(struct ast_channe
2335 static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
2336 static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
2337 static int zt_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
2338+static void enable_dtmf_detect(struct zt_pvt *p);
2339+static void disable_dtmf_detect(struct zt_pvt *p);
2340
2341 static const struct ast_channel_tech zap_tech = {
2342 .type = "Zap",
2343@@ -715,6 +740,13 @@ static const struct ast_channel_tech zap
2344 struct zt_pvt *round_robin[32];
2345
2346 #ifdef HAVE_PRI
2347+struct app_tmp {
2348+ char app[256];
2349+ char data[256];
2350+ struct ast_channel *chan;
2351+ pthread_t t;
2352+};
2353+
2354 static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
2355 {
2356 int res;
2357@@ -1417,12 +1449,16 @@ static void zt_enable_ec(struct zt_pvt *
2358 int res;
2359 if (!p)
2360 return;
2361+ if (p->faxhandled) {
2362+ ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
2363+ return;
2364+ }
2365 if (p->echocanon) {
2366 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
2367 return;
2368 }
2369 if (p->digital) {
2370- ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
2371+ ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
2372 return;
2373 }
2374 if (p->echocancel) {
2375@@ -1449,7 +1485,7 @@ static void zt_train_ec(struct zt_pvt *p
2376 {
2377 int x;
2378 int res;
2379- if (p && p->echocancel && p->echotraining) {
2380+ if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
2381 x = p->echotraining;
2382 res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
2383 if (res)
2384@@ -1810,7 +1846,12 @@ static int zt_call(struct ast_channel *a
2385 ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
2386 p->outgoing = 1;
2387
2388- set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
2389+ if (IS_DIGITAL(ast->transfercapability)) {
2390+ set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
2391+ } else {
2392+ set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
2393+ }
2394+
2395
2396 mysig = p->sig;
2397 if (p->outsigmod > -1)
2398@@ -2041,6 +2082,7 @@ static int zt_call(struct ast_channel *a
2399 case SIG_PRI:
2400 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2401 p->dialdest[0] = '\0';
2402+ disable_dtmf_detect(p);
2403 break;
2404 default:
2405 ast_log(LOG_DEBUG, "not yet implemented\n");
2406@@ -2061,6 +2103,12 @@ static int zt_call(struct ast_channel *a
2407 const char *rr_str;
2408 int redirect_reason;
2409
2410+ if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
2411+ // pass NO audio when ringing an isdn phone
2412+ p->dialing = 1;
2413+ // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
2414+ }
2415+
2416 c = strchr(dest, '/');
2417 if (c)
2418 c++;
2419@@ -2083,6 +2131,7 @@ static int zt_call(struct ast_channel *a
2420 ast_mutex_unlock(&p->lock);
2421 return -1;
2422 }
2423+ strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
2424 if (mysig != SIG_FXSKS) {
2425 p->dop.op = ZT_DIAL_OP_REPLACE;
2426 s = strchr(c + p->stripmsd, 'w');
2427@@ -2106,6 +2155,8 @@ static int zt_call(struct ast_channel *a
2428 pri_rel(p->pri);
2429 ast_mutex_unlock(&p->lock);
2430 return -1;
2431+ } else {
2432+ // ast_log(LOG_NOTICE, "call %d\n", p->call);
2433 }
2434 if (!(sr = pri_sr_new())) {
2435 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2436@@ -2135,7 +2186,7 @@ static int zt_call(struct ast_channel *a
2437 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2438 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2439 (p->digital ? -1 :
2440- ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2441+ ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
2442 if (p->pri->facilityenable)
2443 pri_facility_enable(p->pri->pri);
2444
2445@@ -2399,8 +2450,10 @@ static int pri_find_dchan(struct zt_pri
2446 }
2447 if (newslot < 0) {
2448 newslot = 0;
2449- ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2450+ if (pri->nodetype != BRI_CPE_PTMP) {
2451+ ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2452 pri->dchannels[newslot]);
2453+ }
2454 }
2455 if (old && (oldslot != newslot))
2456 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2457@@ -2410,6 +2463,16 @@ static int pri_find_dchan(struct zt_pri
2458 }
2459 #endif
2460
2461+static int zt_setlaw(int zfd, int law)
2462+{
2463+ int res;
2464+ res = ioctl(zfd, ZT_SETLAW, &law);
2465+ if (res)
2466+ return res;
2467+ return 0;
2468+}
2469+
2470+
2471 static int zt_hangup(struct ast_channel *ast)
2472 {
2473 int res;
2474@@ -2457,8 +2520,7 @@ static int zt_hangup(struct ast_channel
2475 if (option_debug)
2476 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2477 p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
2478- p->ignoredtmf = 0;
2479-
2480+
2481 if (index > -1) {
2482 /* Real channel, do some fixup */
2483 p->subs[index].owner = NULL;
2484@@ -2560,6 +2622,7 @@ static int zt_hangup(struct ast_channel
2485 }
2486
2487 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2488+ int outgoing = p->outgoing;
2489 p->owner = NULL;
2490 p->ringt = 0;
2491 p->distinctivering = 0;
2492@@ -2602,7 +2665,7 @@ static int zt_hangup(struct ast_channel
2493 pri_call_set_useruser(p->call, useruser);
2494 #endif
2495
2496- pri_hangup(p->pri->pri, p->call, -1);
2497+ pri_hangup(p->pri->pri, p->call, -1, -1);
2498 p->call = NULL;
2499 if (p->bearer)
2500 p->bearer->call = NULL;
2501@@ -2622,7 +2685,28 @@ static int zt_hangup(struct ast_channel
2502 if (atoi(cause))
2503 icause = atoi(cause);
2504 }
2505- pri_hangup(p->pri->pri, p->call, icause);
2506+
2507+ pri_hangup(p->pri->pri, p->call, icause, -1);
2508+
2509+ /* if we send a rel9999ease complete we wont ge no hangup event, so clear the call here */
2510+ if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
2511+ if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING) || (ast->_state == AST_STATE_RESERVED)) {
2512+ p->call = NULL;
2513+ } else {
2514+ ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
2515+ icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
2516+ }
2517+ }
2518+
2519+ if (p->pri->nodetype == BRI_NETWORK_PTMP) {
2520+ if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
2521+ if (outgoing) {
2522+ p->call = NULL;
2523+ }
2524+ }
2525+ }
2526+
2527+
2528 }
2529 if (res < 0)
2530 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2531@@ -2806,10 +2890,14 @@ static int zt_answer(struct ast_channel
2532 p->proceeding = 1;
2533 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
2534 pri_rel(p->pri);
2535+ /* stop ignoring inband dtmf */
2536+ enable_dtmf_detect(p);
2537 } else {
2538 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2539 res = -1;
2540 }
2541+ /* the audio path is complete now, train the echo canceler */
2542+ zt_train_ec(p);
2543 break;
2544 #endif
2545 case 0:
2546@@ -3446,6 +3534,15 @@ static int zt_fixup(struct ast_channel *
2547 {
2548 struct zt_pvt *p = newchan->tech_pvt;
2549 int x;
2550+ if (newchan && newchan->tech_pvt) {
2551+ p = newchan->tech_pvt;
2552+ }
2553+ if (!p) {
2554+ if (newchan) {
2555+ ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
2556+ }
2557+ return 0;
2558+ }
2559 ast_mutex_lock(&p->lock);
2560 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
2561 if (p->owner == oldchan) {
2562@@ -3655,8 +3752,10 @@ static void zt_handle_dtmfup(struct ast_
2563 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
2564 if (ast_async_goto(ast, target_context, "fax", 1))
2565 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
2566- } else
2567+ } else {
2568+ if (option_verbose > 2)
2569 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
2570+ }
2571 } else if (option_debug)
2572 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2573 } else if (option_debug)
2574@@ -3815,7 +3914,7 @@ static struct ast_frame *zt_handle_event
2575 if (p->call) {
2576 if (p->pri && p->pri->pri) {
2577 if (!pri_grab(p, p->pri)) {
2578- pri_hangup(p->pri->pri, p->call, -1);
2579+ pri_hangup(p->pri->pri, p->call, -1, -1);
2580 pri_destroycall(p->pri->pri, p->call);
2581 p->call = NULL;
2582 pri_rel(p->pri);
2583@@ -4886,7 +4985,7 @@ static struct ast_frame *zt_read(struct
2584 p->subs[index].f.data = NULL;
2585 p->subs[index].f.datalen= 0;
2586 }
2587- if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
2588+ if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
2589 /* Perform busy detection. etc on the zap line */
2590 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
2591 if (f) {
2592@@ -4898,8 +4997,9 @@ static struct ast_frame *zt_read(struct
2593 }
2594 } else if (f->frametype == AST_FRAME_DTMF) {
2595 #ifdef HAVE_PRI
2596- if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
2597- /* Don't accept in-band DTMF when in overlap dial mode */
2598+ if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
2599+ /* Don't accept in-band DTMF when in overlap dial mode
2600+ or when in non-overlap overlapdialing mode ... */
2601 f->frametype = AST_FRAME_NULL;
2602 f->subclass = 0;
2603 }
2604@@ -4974,7 +5074,9 @@ static int zt_write(struct ast_channel *
2605 #endif
2606 /* Write a frame of (presumably voice) data */
2607 if (frame->frametype != AST_FRAME_VOICE) {
2608- if (frame->frametype != AST_FRAME_IMAGE)
2609+ if (frame->frametype == AST_FRAME_TEXT) {
2610+ ast_log(LOG_NOTICE, "text\n");
2611+ } else if (frame->frametype != AST_FRAME_IMAGE)
2612 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
2613 return 0;
2614 }
2615@@ -5042,7 +5144,7 @@ static int zt_indicate(struct ast_channe
2616 switch (condition) {
2617 case AST_CONTROL_BUSY:
2618 #ifdef HAVE_PRI
2619- if (p->priindication_oob && p->sig == SIG_PRI) {
2620+ if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
2621 chan->hangupcause = AST_CAUSE_USER_BUSY;
2622 chan->_softhangup |= AST_SOFTHANGUP_DEV;
2623 res = 0;
2624@@ -5124,7 +5226,7 @@ static int zt_indicate(struct ast_channe
2625 case AST_CONTROL_CONGESTION:
2626 chan->hangupcause = AST_CAUSE_CONGESTION;
2627 #ifdef HAVE_PRI
2628- if (p->priindication_oob && p->sig == SIG_PRI) {
2629+ if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
2630 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
2631 chan->_softhangup |= AST_SOFTHANGUP_DEV;
2632 res = 0;
2633@@ -5321,8 +5423,12 @@ static struct ast_channel *zt_new(struct
2634 if (state == AST_STATE_RING)
2635 tmp->rings = 1;
2636 tmp->tech_pvt = i;
2637+#ifdef HAVE_PRI
2638+ if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
2639+#else
2640 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
2641- /* Only FXO signalled stuff can be picked up */
2642+#endif
2643+ /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
2644 tmp->callgroup = i->callgroup;
2645 tmp->pickupgroup = i->pickupgroup;
2646 }
2647@@ -5452,6 +5558,7 @@ static void *ss_thread(void *data)
2648 int len = 0;
2649 int res;
2650 int index;
2651+ int network;
2652
2653 /* in the bizarre case where the channel has become a zombie before we
2654 even get started here, abort safely
2655@@ -5480,10 +5587,17 @@ static void *ss_thread(void *data)
2656 len = strlen(exten);
2657 res = 0;
2658 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
2659- if (len && !ast_ignore_pattern(chan->context, exten))
2660+ if (len && !ast_ignore_pattern(chan->context, exten)) {
2661 tone_zone_play_tone(p->subs[index].zfd, -1);
2662- else
2663- tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
2664+ } else {
2665+ network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
2666+ if (network) {
2667+ tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
2668+ } else {
2669+ /* cpe be quiet */
2670+ tone_zone_play_tone(p->subs[index].zfd, -1);
2671+ }
2672+ }
2673 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
2674 timeout = matchdigittimeout;
2675 else
2676@@ -6697,9 +6811,20 @@ static int handle_init_event(struct zt_p
2677 case ZT_EVENT_NOALARM:
2678 i->inalarm = 0;
2679 if (!i->unknown_alarm) {
2680+#ifdef HAVE_PRI
2681+ if (i->pri) {
2682+ if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
2683+ /* dont annoy BRI TE mode users with layer2layer alarms */
2684+ } else {
2685+#endif
2686 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
2687 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
2688 "Channel: %d\r\n", i->channel);
2689+#ifdef HAVE_PRI
2690+ }
2691+ }
2692+#endif
2693+
2694 } else {
2695 i->unknown_alarm = 0;
2696 }
2697@@ -6708,7 +6833,13 @@ static int handle_init_event(struct zt_p
2698 i->inalarm = 1;
2699 res = get_alarms(i);
2700 do {
2701- const char *alarm_str = alarm2str(res);
2702+#ifdef HAVE_PRI
2703+ if (i->pri) {
2704+ if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
2705+ /* dont annoy BRI TE mode users with layer2layer alarms */
2706+ } else {
2707+#endif
2708+ const char *alarm_str = alarm2str(res);
2709
2710 /* hack alert! Zaptel 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
2711 * doesn't know what to do with it. Don't confuse users with log messages. */
2712@@ -6724,6 +6855,10 @@ static int handle_init_event(struct zt_p
2713 "Alarm: %s\r\n"
2714 "Channel: %d\r\n",
2715 alarm_str, i->channel);
2716+#ifdef HAVE_PRI
2717+ }
2718+ }
2719+#endif
2720 } while (0);
2721 /* fall thru intentionally */
2722 case ZT_EVENT_ONHOOK:
2723@@ -6768,8 +6903,10 @@ static int handle_init_event(struct zt_p
2724 zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
2725 break;
2726 case SIG_PRI:
2727- zt_disable_ec(i);
2728- res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
2729+ if (event != ZT_EVENT_ALARM) {
2730+ zt_disable_ec(i);
2731+ res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
2732+ }
2733 break;
2734 default:
2735 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
2736@@ -7062,6 +7199,8 @@ static int pri_resolve_span(int *span, i
2737 } else {
2738 if (si->totalchans == 31) { /* if it's an E1 */
2739 pris[*span].dchannels[0] = 16 + offset;
2740+ } else if (si->totalchans == 3) { /* if it's an S0 ZAPBRI */
2741+ pris[*span].dchannels[0] = 3 + offset;
2742 } else {
2743 pris[*span].dchannels[0] = 24 + offset;
2744 }
2745@@ -7314,6 +7453,11 @@ static struct zt_pvt *mkintf(int channel
2746 destroy_zt_pvt(&tmp);
2747 return NULL;
2748 }
2749+ if ((pris[span].localdialplan) && (pris[span].localdialplan != conf->pri.localdialplan)) {
2750+ ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
2751+ destroy_zt_pvt(&tmp);
2752+ return NULL;
2753+ }
2754 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
2755 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
2756 destroy_zt_pvt(&tmp);
2757@@ -7331,6 +7475,11 @@ static struct zt_pvt *mkintf(int channel
2758 return NULL;
2759 }
2760 pris[span].nodetype = conf->pri.nodetype;
2761+
2762+ if (conf->pri.nodetype == BRI_NETWORK_PTMP) {
2763+ pris[span].dchanavail[0] = DCHAN_AVAILABLE;
2764+ pri_find_dchan(&pris[span]);
2765+ }
2766 pris[span].switchtype = myswitchtype;
2767 pris[span].nsf = conf->pri.nsf;
2768 pris[span].dialplan = conf->pri.dialplan;
2769@@ -7339,9 +7488,13 @@ static struct zt_pvt *mkintf(int channel
2770 pris[span].minunused = conf->pri.minunused;
2771 pris[span].minidle = conf->pri.minidle;
2772 pris[span].overlapdial = conf->pri.overlapdial;
2773+ pris[span].usercid = conf->pri.usercid;
2774+ pris[span].suspended_calls = NULL;
2775 pris[span].facilityenable = conf->pri.facilityenable;
2776 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
2777 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
2778+ ast_copy_string(pris[span].nocid, conf->pri.nocid, sizeof(pris[span].nocid));
2779+ ast_copy_string(pris[span].withheldcid, conf->pri.withheldcid, sizeof(pris[span].withheldcid));
2780 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
2781 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
2782 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
2783@@ -7483,6 +7636,7 @@ static struct zt_pvt *mkintf(int channel
2784 tmp->restrictcid = conf->chan.restrictcid;
2785 tmp->use_callingpres = conf->chan.use_callingpres;
2786 tmp->priindication_oob = conf->chan.priindication_oob;
2787+ tmp->pritransfer = conf->chan.pritransfer;
2788 tmp->priexclusive = conf->chan.priexclusive;
2789 if (tmp->usedistinctiveringdetection) {
2790 if (!tmp->use_callerid) {
2791@@ -7765,7 +7919,7 @@ static int pri_find_empty_chan(struct zt
2792 break;
2793 if (!backwards && (x >= pri->numchans))
2794 break;
2795- if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
2796+ if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
2797 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
2798 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
2799 return x;
2800@@ -7961,6 +8115,11 @@ static struct ast_channel *zt_request(co
2801 p->digital = 1;
2802 if (tmp)
2803 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
2804+ } else if (opt == 'm') {
2805+ /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
2806+ p->faxhandled = 1;
2807+ if (tmp)
2808+ tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
2809 } else {
2810 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
2811 }
2812@@ -7994,13 +8153,14 @@ next:
2813 *cause = AST_CAUSE_BUSY;
2814 } else if (groupmatched) {
2815 *cause = AST_CAUSE_CONGESTION;
2816+ } else {
2817+ *cause = AST_CAUSE_CONGESTION;
2818 }
2819 }
2820
2821 return tmp;
2822 }
2823
2824-
2825 #ifdef HAVE_PRI
2826 static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
2827 {
2828@@ -8045,6 +8205,7 @@ static int pri_find_principle(struct zt_
2829 static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
2830 {
2831 int x;
2832+ int res = 0;
2833 struct zt_pvt *crv;
2834 if (!c) {
2835 if (principle < 0)
2836@@ -8075,6 +8236,7 @@ static int pri_fixup_principle(struct zt
2837 }
2838 /* Fix it all up now */
2839 new->owner = old->owner;
2840+ new->outgoing = old->outgoing;
2841 old->owner = NULL;
2842 if (new->owner) {
2843 ast_string_field_build(new->owner, name,
2844@@ -8094,6 +8256,34 @@ static int pri_fixup_principle(struct zt
2845 new->dsp_features = old->dsp_features;
2846 old->dsp = NULL;
2847 old->dsp_features = 0;
2848+
2849+ /* Copy faxhandled/digial, alreadyhungup */
2850+ new->faxhandled = old->faxhandled;
2851+ new->digital = old->digital;
2852+ new->alreadyhungup = old->alreadyhungup;
2853+
2854+ /* Copy law, gains, etc */
2855+ new->law = old->law;
2856+ if (ioctl(new->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &new->law) == -1)
2857+ ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", new->channel, new->law);
2858+ res = zt_setlaw(new->subs[SUB_REAL].zfd, new->law);
2859+ if (res < 0)
2860+ ast_log(LOG_WARNING, "Unable to set law on channel %d\n", new->channel);
2861+ if (!new->digital) {
2862+ res = set_actual_gain(new->subs[SUB_REAL].zfd, 0, new->rxgain, new->txgain, new->law);
2863+ } else {
2864+ res = set_actual_gain(new->subs[SUB_REAL].zfd, 0, 0, 0, new->law);
2865+ }
2866+ if (res < 0)
2867+ ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", new->channel);
2868+
2869+ /* Shutdown old channel */
2870+ zt_confmute(old, 0);
2871+ update_conf(old);
2872+ reset_conf(old);
2873+ restore_gains(old);
2874+ zt_disable_ec(old);
2875+ zt_setlinear(old->subs[SUB_REAL].zfd, 0);
2876 }
2877 return principle;
2878 }
2879@@ -8122,7 +8312,9 @@ static int pri_fixup_principle(struct zt
2880 }
2881 crv = crv->next;
2882 }
2883- ast_log(LOG_WARNING, "Call specified, but not found?\n");
2884+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
2885+ ast_log(LOG_WARNING, "Call specified, but not found?\n");
2886+ }
2887 return -1;
2888 }
2889
2890@@ -8181,86 +8373,21 @@ static void *do_idle_thread(void *vchan)
2891 #ifndef PRI_RESTART
2892 #error "Upgrade your libpri"
2893 #endif
2894-static void zt_pri_message(struct pri *pri, char *s)
2895+static void zt_pri_message(char *s, int span)
2896 {
2897- int x, y;
2898- int dchan = -1, span = -1;
2899- int dchancount = 0;
2900-
2901- if (pri) {
2902- for (x = 0; x < NUM_SPANS; x++) {
2903- for (y = 0; y < NUM_DCHANS; y++) {
2904- if (pris[x].dchans[y])
2905- dchancount++;
2906-
2907- if (pris[x].dchans[y] == pri)
2908- dchan = y;
2909- }
2910- if (dchan >= 0) {
2911- span = x;
2912- break;
2913- }
2914- dchancount = 0;
2915- }
2916- if ((dchan >= 0) && (span >= 0)) {
2917- if (dchancount > 1)
2918- ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
2919- else
2920- ast_verbose("%s", s);
2921- } else
2922- ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
2923- } else
2924- ast_verbose("%s", s);
2925-
2926- ast_mutex_lock(&pridebugfdlock);
2927-
2928- if (pridebugfd >= 0)
2929- write(pridebugfd, s, strlen(s));
2930-
2931- ast_mutex_unlock(&pridebugfdlock);
2932+ ast_verbose("%d %s", span, s);
2933 }
2934
2935-static void zt_pri_error(struct pri *pri, char *s)
2936+static void zt_pri_error(char *s, int span)
2937 {
2938- int x, y;
2939- int dchan = -1, span = -1;
2940- int dchancount = 0;
2941-
2942- if (pri) {
2943- for (x = 0; x < NUM_SPANS; x++) {
2944- for (y = 0; y < NUM_DCHANS; y++) {
2945- if (pris[x].dchans[y])
2946- dchancount++;
2947-
2948- if (pris[x].dchans[y] == pri)
2949- dchan = y;
2950- }
2951- if (dchan >= 0) {
2952- span = x;
2953- break;
2954- }
2955- dchancount = 0;
2956- }
2957- if ((dchan >= 0) && (span >= 0)) {
2958- if (dchancount > 1)
2959- ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
2960- else
2961- ast_log(LOG_ERROR, "%s", s);
2962- } else
2963- ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
2964- } else
2965- ast_log(LOG_ERROR, "%s", s);
2966-
2967- ast_mutex_lock(&pridebugfdlock);
2968-
2969- if (pridebugfd >= 0)
2970- write(pridebugfd, s, strlen(s));
2971-
2972- ast_mutex_unlock(&pridebugfdlock);
2973+ ast_log(LOG_WARNING, "%d %s", span, s);
2974 }
2975
2976 static int pri_check_restart(struct zt_pri *pri)
2977 {
2978+ if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
2979+ return 0;
2980+ }
2981 do {
2982 pri->resetpos++;
2983 } while ((pri->resetpos < pri->numchans) &&
2984@@ -8344,13 +8471,30 @@ static void apply_plan_to_number(char *b
2985 }
2986 }
2987
2988-static int zt_setlaw(int zfd, int law)
2989-{
2990- int res;
2991- res = ioctl(zfd, ZT_SETLAW, &law);
2992- if (res)
2993- return res;
2994- return 0;
2995+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) {
2996+ if (callingnum && (callingnum_len > stripmsd)) {
2997+ callingnum += stripmsd;
2998+ }
2999+ switch (callingplan) {
3000+ case PRI_INTERNATIONAL_ISDN:
3001+ snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
3002+ break;
3003+ case PRI_NATIONAL_ISDN:
3004+ snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
3005+ break;
3006+ case PRI_LOCAL_ISDN:
3007+ snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
3008+ break;
3009+ case PRI_PRIVATE:
3010+ snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
3011+ break;
3012+ case PRI_UNKNOWN:
3013+ snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
3014+ break;
3015+ default:
3016+ snprintf(callerid, callerid_len, "%s", callingnum);
3017+ break;
3018+ }
3019 }
3020
3021 static void *pri_dchannel(void *vpri)
3022@@ -8530,15 +8674,44 @@ static void *pri_dchannel(void *vpri)
3023 /* Check for an event */
3024 x = 0;
3025 res = ioctl(pri->fds[which], ZT_GETEVENT, &x);
3026- if (x)
3027+ if ((pri->nodetype != BRI_CPE) && (pri->nodetype != BRI_CPE_PTMP)) {
3028+ /* dont annoy BRI TE mode users with layer2layer alarms */
3029+ if (x)
3030 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);
3031+ }
3032 /* Keep track of alarm state */
3033 if (x == ZT_EVENT_ALARM) {
3034 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
3035 pri_find_dchan(pri);
3036+ if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
3037+ if (pri->pri) {
3038+ for (i=0; i<pri->numchans; i++) {
3039+ struct zt_pvt *p = pri->pvts[i];
3040+ if (p) {
3041+ if (p->call) {
3042+ if (p->pri && p->pri->pri) {
3043+ pri_destroycall(p->pri->pri, p->call);
3044+ p->call = NULL;
3045+ p->tei = -1;
3046+ } else
3047+ ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
3048+ }
3049+ if (p->owner)
3050+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3051+ p->inalarm = 1;
3052+ }
3053+ }
3054+ pri_shutdown(pri->pri);
3055+ }
3056+ }
3057 } else if (x == ZT_EVENT_NOALARM) {
3058- pri->dchanavail[which] |= DCHAN_NOTINALARM;
3059- pri_restart(pri->dchans[which]);
3060+ if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
3061+ pri->dchanavail[which] |= DCHAN_NOTINALARM;
3062+ // pri->dchanavail[which] |= DCHAN_UP;
3063+ } else {
3064+ pri->dchanavail[which] |= DCHAN_NOTINALARM;
3065+ pri_restart(pri->dchans[which]);
3066+ }
3067 }
3068
3069 if (option_debug)
3070@@ -8550,8 +8723,7 @@ static void *pri_dchannel(void *vpri)
3071 break;
3072 }
3073 } else if (errno != EINTR)
3074- ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
3075-
3076+ ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
3077 if (e) {
3078 if (pri->debug)
3079 pri_dump_event(pri->dchans[which], e);
3080@@ -8576,6 +8748,17 @@ static void *pri_dchannel(void *vpri)
3081
3082 switch (e->e) {
3083 case PRI_EVENT_DCHAN_UP:
3084+ if (pri->nodetype == BRI_NETWORK_PTMP) {
3085+ if (option_verbose > 3)
3086+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
3087+ } else if (pri->nodetype == BRI_CPE_PTMP) {
3088+ if (option_verbose > 3)
3089+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
3090+ } else {
3091+ if (option_verbose > 1)
3092+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
3093+ }
3094+
3095 if (!pri->pri) pri_find_dchan(pri);
3096
3097 /* Note presense of D-channel */
3098@@ -8594,6 +8777,12 @@ static void *pri_dchannel(void *vpri)
3099 }
3100 break;
3101 case PRI_EVENT_DCHAN_DOWN:
3102+ if (pri->nodetype == BRI_NETWORK_PTMP) {
3103+ if (option_verbose > 3)
3104+ ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
3105+ // PTMP BRIs have N dchans, handled by libpri
3106+ if (e->gen.tei == 0) break;
3107+ }
3108 pri_find_dchan(pri);
3109 if (!pri_is_up(pri)) {
3110 pri->resetting = 0;
3111@@ -8601,16 +8790,18 @@ static void *pri_dchannel(void *vpri)
3112 for (i = 0; i < pri->numchans; i++) {
3113 struct zt_pvt *p = pri->pvts[i];
3114 if (p) {
3115+ if ((p->tei == e->gen.tei) || (pri->nodetype != BRI_NETWORK_PTMP)) {
3116 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
3117 /* T309 is not enabled : hangup calls when alarm occurs */
3118 if (p->call) {
3119 if (p->pri && p->pri->pri) {
3120- pri_hangup(p->pri->pri, p->call, -1);
3121+ pri_hangup(p->pri->pri, p->call, -1, -1);
3122 pri_destroycall(p->pri->pri, p->call);
3123 p->call = NULL;
3124 } else
3125 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
3126 }
3127+ p->tei = -1;
3128 if (p->realcall) {
3129 pri_hangup_all(p->realcall, pri);
3130 } else if (p->owner)
3131@@ -8619,6 +8810,7 @@ static void *pri_dchannel(void *vpri)
3132 p->inalarm = 1;
3133 }
3134 }
3135+ }
3136 }
3137 break;
3138 case PRI_EVENT_RESTART:
3139@@ -8653,8 +8845,8 @@ static void *pri_dchannel(void *vpri)
3140 pri_destroycall(pri->pri, pri->pvts[x]->call);
3141 pri->pvts[x]->call = NULL;
3142 }
3143- if (pri->pvts[chanpos]->realcall)
3144- pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
3145+ if (pri->pvts[x]->realcall)
3146+ pri_hangup_all(pri->pvts[x]->realcall, pri);
3147 else if (pri->pvts[x]->owner)
3148 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3149 ast_mutex_unlock(&pri->pvts[x]->lock);
3150@@ -8688,7 +8880,6 @@ static void *pri_dchannel(void *vpri)
3151 }
3152 }
3153 break;
3154-
3155 case PRI_EVENT_INFO_RECEIVED:
3156 chanpos = pri_find_principle(pri, e->ring.channel);
3157 if (chanpos < 0) {
3158@@ -8697,9 +8888,11 @@ static void *pri_dchannel(void *vpri)
3159 } else {
3160 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
3161 if (chanpos > -1) {
3162+// ast_log(LOG_NOTICE, "INFO received on channel %d/%d span %d\n",
3163+// PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3164 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3165 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
3166- if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
3167+ if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
3168 /* how to do that */
3169 int digitlen = strlen(e->ring.callednum);
3170 char digit;
3171@@ -8711,6 +8904,14 @@ static void *pri_dchannel(void *vpri)
3172 zap_queue_frame(pri->pvts[chanpos], &f, pri);
3173 }
3174 }
3175+ if (!pri->overlapdial) {
3176+ strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
3177+ if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
3178+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
3179+ } else {
3180+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
3181+ }
3182+ }
3183 }
3184 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3185 }
3186@@ -8718,36 +8919,59 @@ static void *pri_dchannel(void *vpri)
3187 break;
3188 case PRI_EVENT_RING:
3189 crv = NULL;
3190- if (e->ring.channel == -1)
3191+ if (e->ring.channel == -1) {
3192+ /* if no channel specified find one empty */
3193 chanpos = pri_find_empty_chan(pri, 1);
3194- else
3195+ } else {
3196 chanpos = pri_find_principle(pri, e->ring.channel);
3197+ }
3198 /* if no channel specified find one empty */
3199 if (chanpos < 0) {
3200- ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
3201- PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3202+ /* no channel specified and no free channel. this is a callwating SETUP */
3203+ if (e->ring.channel <= 0) {
3204+ if (option_verbose > 2)
3205+ 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);
3206+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY, -1);
3207+ break;
3208+ }
3209 } else {
3210+ /* ok, we got a b channel for this call, lock it */
3211 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3212 if (pri->pvts[chanpos]->owner) {
3213- if (pri->pvts[chanpos]->call == e->ring.call) {
3214- ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
3215+ /* safety check, for messed up retransmissions? */
3216+ if (pri->pvts[chanpos]->call == e->ring.call) {
3217+ ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
3218 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3219- break;
3220+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3221+ chanpos = -1;
3222+ break;
3223+ } else {
3224+ ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
3225+ PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3226+ if (pri->pvts[chanpos]->realcall) {
3227+ pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
3228 } else {
3229- /* This is where we handle initial glare */
3230- ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
3231- PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3232- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3233- chanpos = -1;
3234+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3235+ /* XXX destroy the call here, so we can accept the retransmission as a new call */
3236+ pri_destroycall(pri->pri, e->ring.call);
3237 }
3238- }
3239- if (chanpos > -1)
3240 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3241+ chanpos = -1;
3242+ break;
3243+ }
3244+ }
3245+ if (chanpos > -1) {
3246+ /* everything is ok with the b channel */
3247+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3248+ }
3249 }
3250- if ((chanpos < 0) && (e->ring.flexible))
3251- chanpos = pri_find_empty_chan(pri, 1);
3252+ /* actually, we already got a valid channel by now */
3253 if (chanpos > -1) {
3254 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3255+ /* dont detect dtmfs before the signalling is done */
3256+ disable_dtmf_detect(pri->pvts[chanpos]);
3257+ /* this channel is owned by this TEI */
3258+ pri->pvts[chanpos]->tei = e->ring.tei;
3259 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
3260 /* Should be safe to lock CRV AFAIK while bearer is still locked */
3261 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
3262@@ -8761,13 +8985,14 @@ static void *pri_dchannel(void *vpri)
3263 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);
3264 } else
3265 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);
3266- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
3267+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE, -1);
3268 if (crv)
3269 ast_mutex_unlock(&crv->lock);
3270 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3271 break;
3272 }
3273 }
3274+ /* assign call to b channel */
3275 pri->pvts[chanpos]->call = e->ring.call;
3276 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
3277 if (pri->pvts[chanpos]->use_callerid) {
3278@@ -8792,34 +9017,82 @@ static void *pri_dchannel(void *vpri)
3279 }
3280 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
3281 e->ring.redirectingnum, e->ring.callingplanrdnis);
3282+ /* get callingpres */
3283+ pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
3284+ switch (e->ring.callingpres) {
3285+ case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
3286+ case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
3287+ case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
3288+ case PRES_PROHIB_NETWORK_NUMBER:
3289+ ast_copy_string(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
3290+ break;
3291+ case PRES_NUMBER_NOT_AVAILABLE:
3292+ ast_copy_string(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
3293+ break;
3294+ }
3295 /* If immediate=yes go to s|1 */
3296 if (pri->pvts[chanpos]->immediate) {
3297 if (option_verbose > 2)
3298 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
3299 pri->pvts[chanpos]->exten[0] = 's';
3300 pri->pvts[chanpos]->exten[1] = '\0';
3301- }
3302- /* Get called number */
3303- else if (!ast_strlen_zero(e->ring.callednum)) {
3304- ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
3305- ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
3306- } else if (pri->overlapdial)
3307- pri->pvts[chanpos]->exten[0] = '\0';
3308- else {
3309- /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
3310- pri->pvts[chanpos]->exten[0] = 's';
3311- pri->pvts[chanpos]->exten[1] = '\0';
3312- }
3313- /* Set DNID on all incoming calls -- even immediate */
3314- if (!ast_strlen_zero(e->ring.callednum))
3315- ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
3316- /* No number yet, but received "sending complete"? */
3317- if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
3318+ } else if (ast_strlen_zero(e->ring.callednum)) {
3319+ /* called party number is empty */
3320+ if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
3321+ if (!pri->overlapdial) {
3322+ // be able to set digittimeout for BRI phones
3323+ pri->pvts[chanpos]->exten[0] = 's';
3324+ pri->pvts[chanpos]->exten[1] = '\0';
3325+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
3326+ } else {
3327+ pri->pvts[chanpos]->exten[0] = '\0';
3328+ }
3329+ } else {
3330+ if (pri->nodetype == BRI_CPE) {
3331+ /* fix for .at p2p bri lines */
3332+ pri->pvts[chanpos]->exten[0] = 's';
3333+ pri->pvts[chanpos]->exten[1] = '\0';
3334+ } else if (pri->overlapdial) {
3335+ pri->pvts[chanpos]->exten[0] = '\0';
3336+ } else {
3337+ /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
3338+ pri->pvts[chanpos]->exten[0] = 's';
3339+ pri->pvts[chanpos]->exten[1] = '\0';
3340+ }
3341+ }
3342+ /* No number yet, but received "sending complete"? */
3343+ if (e->ring.complete) {
3344 if (option_verbose > 2)
3345 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
3346 pri->pvts[chanpos]->exten[0] = 's';
3347 pri->pvts[chanpos]->exten[1] = '\0';
3348- }
3349+ }
3350+ } else {
3351+ /* Get called number */
3352+ 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);
3353+ 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);
3354+ if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
3355+ /* if we get the next digit we should stop the dialtone */
3356+ if (!pri->overlapdial) {
3357+ // with overlapdial=no the exten is always prefixed by "s"
3358+ if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
3359+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
3360+ } else {
3361+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
3362+ }
3363+ } else {
3364+ if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
3365+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
3366+ } else {
3367+ tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
3368+ }
3369+ }
3370+ }
3371+ }
3372+ /* Part 3: create channel, setup audio... */
3373+ /* Set DNID on all incoming calls -- even immediate */
3374+ if (!ast_strlen_zero(e->ring.callednum))
3375+ strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
3376 /* Make sure extension exists (or in overlap dial mode, can exist) */
3377 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
3378 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
3379@@ -8838,19 +9111,36 @@ static void *pri_dchannel(void *vpri)
3380 res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
3381 if (res < 0)
3382 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
3383- res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
3384+ if (IS_DIGITAL(e->ring.ctype)) {
3385+ res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
3386+ } else {
3387+ res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
3388+ }
3389 if (res < 0)
3390 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
3391- if (e->ring.complete || !pri->overlapdial) {
3392+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3393+ if (e->ring.complete || !pri->overlapdial) {
3394 /* Just announce proceeding */
3395 pri->pvts[chanpos]->proceeding = 1;
3396 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
3397- } else {
3398+ } else {
3399 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
3400 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
3401 else
3402 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
3403+ }
3404+ } else {
3405+ /* BRI_NETWORK | BRI_NETWORK_PTMP */
3406+ if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
3407+ /* send a SETUP_ACKNOWLEDGE */
3408+ pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
3409+ } else {
3410+ /* send an ALERTING ??? wtf */
3411+ // pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
3412+ pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
3413+ }
3414 }
3415+ /* overlapdial = yes and the extension can be valid */
3416 /* Get the use_callingpres state */
3417 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
3418
3419@@ -8862,10 +9152,17 @@ static void *pri_dchannel(void *vpri)
3420 /* Set bearer and such */
3421 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
3422 c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
3423+ if (c && (e->ring.lowlayercompat[0] > 0)) {
3424+ memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
3425+ }
3426 pri->pvts[chanpos]->owner = &inuse;
3427 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
3428 } else {
3429 c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
3430+ if (c && (e->ring.lowlayercompat[0] > 0)) {
3431+ memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
3432+ }
3433+ zt_enable_ec(pri->pvts[chanpos]); /* XXX rethink */
3434 }
3435
3436 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3437@@ -8873,6 +9170,16 @@ static void *pri_dchannel(void *vpri)
3438 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
3439 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
3440 }
3441+ if (!ast_strlen_zero(e->ring.callingnum)) {
3442+ char tmpstr[256];
3443+ pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
3444+ pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
3445+ }
3446+ if (!ast_strlen_zero(e->ring.callingani)) {
3447+ char tmpstr[256];
3448+ pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
3449+ pbx_builtin_setvar_helper(c, "PRI_USER_CID", tmpstr);
3450+ }
3451 if (e->ring.ani2 >= 0) {
3452 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
3453 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
3454@@ -8896,8 +9203,8 @@ static void *pri_dchannel(void *vpri)
3455 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3456 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
3457 if (option_verbose > 2)
3458- ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
3459- plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
3460+ ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
3461+ pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
3462 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
3463 } else {
3464 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
3465@@ -8905,15 +9212,19 @@ static void *pri_dchannel(void *vpri)
3466 if (c)
3467 ast_hangup(c);
3468 else {
3469- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
3470+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
3471 pri->pvts[chanpos]->call = NULL;
3472 }
3473 }
3474 pthread_attr_destroy(&attr);
3475 } else {
3476+ /* overlapdial = no */
3477 ast_mutex_unlock(&pri->lock);
3478 /* Release PRI lock while we create the channel */
3479 c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
3480+ if (c && (e->ring.lowlayercompat[0] > 0)) {
3481+ memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
3482+ }
3483 if (c) {
3484 char calledtonstr[10];
3485
3486@@ -8940,26 +9251,43 @@ static void *pri_dchannel(void *vpri)
3487 ast_mutex_lock(&pri->lock);
3488
3489 if (option_verbose > 2)
3490- ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
3491- plancallingnum, pri->pvts[chanpos]->exten,
3492+ ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
3493+ pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten,
3494 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
3495 zt_enable_ec(pri->pvts[chanpos]);
3496+ if(!ast_strlen_zero(e->ring.callingsubaddr)) {
3497+ pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
3498+ }
3499+ if (!ast_strlen_zero(e->ring.callingnum)) {
3500+ char tmpstr[256];
3501+ pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
3502+ pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
3503+ }
3504+ if (!ast_strlen_zero(e->ring.callingani)) {
3505+ char tmpstr[256];
3506+ pri_make_callerid(pri, tmpstr,sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
3507+ pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
3508+ }
3509+ if (!ast_strlen_zero(e->ring.useruserinfo)) {
3510+ pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
3511+ }
3512 } else {
3513
3514 ast_mutex_lock(&pri->lock);
3515
3516 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
3517 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
3518- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
3519+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
3520 pri->pvts[chanpos]->call = NULL;
3521 }
3522 }
3523 } else {
3524+ /* invalid extension */
3525 if (option_verbose > 2)
3526 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
3527 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
3528 pri->pvts[chanpos]->prioffset, pri->span);
3529- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
3530+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED, -1);
3531 pri->pvts[chanpos]->call = NULL;
3532 pri->pvts[chanpos]->exten[0] = '\0';
3533 }
3534@@ -8968,9 +9296,9 @@ static void *pri_dchannel(void *vpri)
3535 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3536 } else {
3537 if (e->ring.flexible)
3538- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
3539+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION, -1);
3540 else
3541- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
3542+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, -1);
3543 }
3544 break;
3545 case PRI_EVENT_RINGING:
3546@@ -8986,7 +9314,7 @@ static void *pri_dchannel(void *vpri)
3547 } else {
3548 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3549 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
3550- zt_enable_ec(pri->pvts[chanpos]);
3551+ // XXX zt_enable_ec(pri->pvts[chanpos]);
3552 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
3553 pri->pvts[chanpos]->alerting = 1;
3554 } else
3555@@ -9018,9 +9346,16 @@ static void *pri_dchannel(void *vpri)
3556 }
3557 break;
3558 case PRI_EVENT_PROGRESS:
3559- /* Get chan value if e->e is not PRI_EVNT_RINGING */
3560+ /* Get chan value if e->e is not PRI_EVENT_RINGING */
3561 chanpos = pri_find_principle(pri, e->proceeding.channel);
3562 if (chanpos > -1) {
3563+ if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
3564+ /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
3565+ if (pri->pvts[chanpos]->owner) {
3566+ pri->pvts[chanpos]->owner->hangupcause = AST_CAUSE_USER_BUSY;
3567+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3568+ }
3569+ } else {
3570 #ifdef PRI_PROGRESS_MASK
3571 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
3572 #else
3573@@ -9062,11 +9397,18 @@ static void *pri_dchannel(void *vpri)
3574 pri->pvts[chanpos]->progress = 1;
3575 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3576 }
3577+ }
3578 }
3579 break;
3580 case PRI_EVENT_PROCEEDING:
3581 chanpos = pri_find_principle(pri, e->proceeding.channel);
3582 if (chanpos > -1) {
3583+ chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
3584+ if (chanpos < 0) {
3585+ ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n",
3586+ PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
3587+ chanpos = -1;
3588+ } else {
3589 if (!pri->pvts[chanpos]->proceeding) {
3590 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
3591
3592@@ -9091,6 +9433,7 @@ static void *pri_dchannel(void *vpri)
3593 pri->pvts[chanpos]->proceeding = 1;
3594 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3595 }
3596+ }
3597 }
3598 break;
3599 case PRI_EVENT_FACNAME:
3600@@ -9114,6 +9457,163 @@ static void *pri_dchannel(void *vpri)
3601 }
3602 }
3603 break;
3604+ case PRI_EVENT_SUSPEND_REQ:
3605+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3606+ pri_suspend_reject(pri->pri, e->suspend_req.call, "");
3607+ break;
3608+ }
3609+ chanpos = pri_find_principle(pri, e->suspend_req.channel);
3610+ if (chanpos < 0) {
3611+ ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
3612+ chanpos = -1;
3613+ }
3614+
3615+ if (chanpos > -1) {
3616+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
3617+ if (pri->pvts[chanpos]->owner) {
3618+ if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
3619+ struct zt_suspended_call *zpc;
3620+ char tmpstr[256];
3621+ zpc = malloc(sizeof(struct zt_suspended_call));
3622+ if (!zpc) {
3623+ ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
3624+ break;
3625+ }
3626+ strncpy(zpc->msn, pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
3627+ strncpy(zpc->callid, e->suspend_req.callid, sizeof(zpc->callid));
3628+ ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
3629+ zpc->next = pri->suspended_calls;
3630+ pri->suspended_calls = zpc;
3631+ snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
3632+ pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
3633+ pri->pvts[chanpos]->call = NULL;
3634+ pri->pvts[chanpos]->tei = -1;
3635+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3636+ } else {
3637+ pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
3638+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3639+ break;
3640+ }
3641+ } else {
3642+ pri_suspend_reject(pri->pri, e->suspend_req.call, "");
3643+ }
3644+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3645+ }
3646+ break;
3647+ case PRI_EVENT_RESUME_REQ:
3648+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3649+ break;
3650+ }
3651+ chanpos = pri_find_empty_chan(pri, 1);
3652+ if (chanpos < 0) {
3653+ pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
3654+ ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
3655+ chanpos = -1;
3656+ } else if (!pri->pvts[chanpos]) {
3657+ pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
3658+ chanpos = -1;
3659+ }
3660+
3661+ if (chanpos > -1) {
3662+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
3663+ if (!pri->pvts[chanpos]->owner) {
3664+ struct zt_suspended_call *zpc, *zpcl;
3665+ int unparked=0;
3666+ char extenstr[255], temp[255];
3667+ zpc = NULL;
3668+ zpcl = pri->suspended_calls;
3669+ while (zpcl) {
3670+ // ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
3671+ if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
3672+ int law;
3673+ // found a parked call
3674+ snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
3675+ strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
3676+ // strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
3677+ pri->pvts[chanpos]->call = e->resume_req.call;
3678+ law = 1;
3679+ if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
3680+ ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
3681+ // uhh ohh...what shall we do without the bearer cap???
3682+ law = ZT_LAW_ALAW;
3683+ res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
3684+ if (res < 0)
3685+ ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
3686+ if (!pri->pvts[chanpos]->digital) {
3687+ res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
3688+ } else {
3689+ res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
3690+ }
3691+ if (res < 0)
3692+ ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
3693+ /* Start PBX */
3694+ c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
3695+ if (c) {
3696+ pri->pvts[chanpos]->owner = c;
3697+ pri->pvts[chanpos]->call = e->resume_req.call;
3698+ zt_enable_ec(pri->pvts[chanpos]);
3699+ zt_train_ec(pri->pvts[chanpos]);
3700+ } else {
3701+ ast_log(LOG_ERROR, "unable to start pbx\n");
3702+ }
3703+
3704+ if (zpc) {
3705+ zpc->next = zpcl->next;
3706+ free(zpcl);
3707+ zpcl = zpc->next;
3708+ } else {
3709+ // remove head
3710+ pri->suspended_calls = zpcl->next;
3711+ free(zpcl);
3712+ zpcl = pri->suspended_calls;
3713+ zpc = NULL;
3714+ }
3715+ unparked = 1;
3716+ snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
3717+ pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
3718+ break;
3719+ }
3720+ zpc = zpcl;
3721+ if (zpcl) zpcl = zpcl->next;
3722+ }
3723+ if (!unparked)
3724+ pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
3725+ } else {
3726+ pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
3727+ }
3728+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3729+ }
3730+ break;
3731+ case PRI_EVENT_HOLD_REQ:
3732+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3733+ pri_hold_reject(pri->pri, e->hold_req.call);
3734+ break;
3735+ }
3736+ /* holded calls are not implemented yet */
3737+ pri_hold_reject(pri->pri, e->hold_req.call);
3738+ break;
3739+ case PRI_EVENT_RETRIEVE_REQ:
3740+ if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3741+ pri_retrieve_reject(pri->pri, e->retrieve_req.call);
3742+ break;
3743+ }
3744+ /* Holded calls are currently not supported */
3745+ pri_retrieve_reject(pri->pri, e->retrieve_req.call);
3746+ chanpos = -1;
3747+ break;
3748+ case PRI_EVENT_DISPLAY_RECEIVED:
3749+ ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
3750+ chanpos = pri_find_principle(pri, e->display.channel);
3751+ if (chanpos < 0) {
3752+ ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
3753+ chanpos = -1;
3754+ }
3755+ if (chanpos > -1) {
3756+ if (pri->pvts[chanpos]->owner) {
3757+ // ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
3758+ }
3759+ }
3760+ break;
3761 case PRI_EVENT_ANSWER:
3762 chanpos = pri_find_principle(pri, e->answer.channel);
3763 if (chanpos < 0) {
3764@@ -9126,6 +9626,7 @@ static void *pri_dchannel(void *vpri)
3765 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
3766 } else {
3767 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3768+ pri->pvts[chanpos]->tei = e->answer.tei;
3769 /* Now we can do call progress detection */
3770
3771 /* We changed this so it turns on the DSP no matter what... progress or no progress.
3772@@ -9155,11 +9656,16 @@ static void *pri_dchannel(void *vpri)
3773 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
3774 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
3775 } else if (pri->pvts[chanpos]->confirmanswer) {
3776- ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
3777+ ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
3778+ enable_dtmf_detect(pri->pvts[chanpos]);
3779 } else {
3780+ pri->pvts[chanpos]->dialing = 0;
3781 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
3782 /* Enable echo cancellation if it's not on already */
3783 zt_enable_ec(pri->pvts[chanpos]);
3784+ zt_train_ec(pri->pvts[chanpos]);
3785+ /* stop ignoring inband dtmf */
3786+ enable_dtmf_detect(pri->pvts[chanpos]);
3787 }
3788
3789 #ifdef SUPPORT_USERUSER
3790@@ -9216,20 +9722,29 @@ static void *pri_dchannel(void *vpri)
3791 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
3792 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
3793 } else {
3794- pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
3795+ pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
3796 pri->pvts[chanpos]->call = NULL;
3797+ pri->pvts[chanpos]->tei = -1;
3798 }
3799 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
3800- if (option_verbose > 2)
3801+ if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
3802+ if (option_verbose > 2)
3803 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
3804- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3805- pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
3806- pri->pvts[chanpos]->resetting = 1;
3807- }
3808- if (e->hangup.aoc_units > -1)
3809+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3810+ pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
3811+ pri->pvts[chanpos]->resetting = 1;
3812+ }
3813+ }
3814+ if (e->hangup.aoc_units > -1) {
3815+ if (pri->pvts[chanpos]->owner) {
3816+ char tmpstr[256];
3817+ snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
3818+ pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
3819+ }
3820 if (option_verbose > 2)
3821 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
3822 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
3823+ }
3824
3825 #ifdef SUPPORT_USERUSER
3826 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
3827@@ -9242,8 +9757,9 @@ static void *pri_dchannel(void *vpri)
3828
3829 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3830 } else {
3831- ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
3832- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3833+ ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
3834+ ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
3835+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3836 }
3837 }
3838 break;
3839@@ -9253,15 +9769,23 @@ static void *pri_dchannel(void *vpri)
3840 case PRI_EVENT_HANGUP_REQ:
3841 chanpos = pri_find_principle(pri, e->hangup.channel);
3842 if (chanpos < 0) {
3843- ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
3844- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3845- } else {
3846+ if (pri->nodetype == BRI_NETWORK_PTMP) {
3847+ pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
3848+ } else {
3849+ ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
3850+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3851+ }
3852+ } else if ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing)) {
3853+ /* dont hang up if we want to hear inband call progress */
3854 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
3855 if (chanpos > -1) {
3856 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3857 if (pri->pvts[chanpos]->realcall)
3858 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
3859 else if (pri->pvts[chanpos]->owner) {
3860+ char tmpstr[256];
3861+ snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
3862+ pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
3863 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
3864 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
3865 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3866@@ -9288,16 +9812,34 @@ static void *pri_dchannel(void *vpri)
3867 if (option_verbose > 2)
3868 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
3869 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
3870+ if (e->hangup.aoc_units > -1) {
3871+ if (pri->pvts[chanpos]->owner) {
3872+ char tmpstr[256];
3873+ snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
3874+ pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
3875+ }
3876+ if (option_verbose > 2)
3877+ ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
3878+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
3879+ }
3880+ if (pri->nodetype == BRI_NETWORK_PTMP) {
3881+ pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
3882+ pri->pvts[chanpos]->call = NULL;
3883+ pri->pvts[chanpos]->tei = -1;
3884+ }
3885 } else {
3886- pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
3887+ pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
3888 pri->pvts[chanpos]->call = NULL;
3889+ pri->pvts[chanpos]->tei = -1;
3890 }
3891 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
3892- if (option_verbose > 2)
3893+ if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
3894+ if (option_verbose > 2)
3895 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
3896 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3897- pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
3898- pri->pvts[chanpos]->resetting = 1;
3899+ pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
3900+ pri->pvts[chanpos]->resetting = 1;
3901+ }
3902 }
3903
3904 #ifdef SUPPORT_USERUSER
3905@@ -9311,9 +9853,27 @@ static void *pri_dchannel(void *vpri)
3906
3907 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3908 } else {
3909- 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);
3910+ if (pri->nodetype != BRI_NETWORK_PTMP) {
3911+ 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);
3912+ } else {
3913+ 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);
3914+ }
3915 }
3916 }
3917+ if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
3918+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
3919+ if (e->hangup.aoc_units > -1) {
3920+ char tmpstr[256];
3921+ snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
3922+ pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
3923+ if (option_verbose > 2)
3924+ ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
3925+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
3926+ }
3927+ pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
3928+ ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
3929+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3930+ }
3931 break;
3932 case PRI_EVENT_HANGUP_ACK:
3933 chanpos = pri_find_principle(pri, e->hangup.channel);
3934@@ -9325,6 +9885,7 @@ static void *pri_dchannel(void *vpri)
3935 if (chanpos > -1) {
3936 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3937 pri->pvts[chanpos]->call = NULL;
3938+ pri->pvts[chanpos]->tei = -1;
3939 pri->pvts[chanpos]->resetting = 0;
3940 if (pri->pvts[chanpos]->owner) {
3941 if (option_verbose > 2)
3942@@ -9431,10 +9992,22 @@ static void *pri_dchannel(void *vpri)
3943 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3944 switch (e->notify.info) {
3945 case PRI_NOTIFY_REMOTE_HOLD:
3946+ if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
3947+ ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
3948+ ast_moh_start(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, pri->pvts[chanpos]->mohinterpret);
3949+ } else {
3950+ ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
3951+ }
3952 f.subclass = AST_CONTROL_HOLD;
3953 zap_queue_frame(pri->pvts[chanpos], &f, pri);
3954 break;
3955 case PRI_NOTIFY_REMOTE_RETRIEVAL:
3956+ if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
3957+ ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
3958+ ast_moh_stop(ast_bridged_channel(pri->pvts[chanpos]->owner));
3959+ } else {
3960+ ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
3961+ }
3962 f.subclass = AST_CONTROL_UNHOLD;
3963 zap_queue_frame(pri->pvts[chanpos], &f, pri);
3964 break;
3965@@ -9442,6 +10015,23 @@ static void *pri_dchannel(void *vpri)
3966 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3967 }
3968 break;
3969+ case PRI_EVENT_FACILITY:
3970+ if (e->facility.operation == 0x0D) {
3971+ struct ast_channel *owner = pri->pvts[chanpos]->owner;
3972+
3973+ ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
3974+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
3975+ /* transfer */
3976+ if (owner) {
3977+ ast_string_field_build(owner, call_forward,
3978+ "Local/%s@%s", e->facility.forwardnum,
3979+ owner->context);
3980+ }
3981+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3982+ } else {
3983+ ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
3984+ }
3985+ break;
3986 default:
3987 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
3988 }
3989@@ -9503,7 +10093,7 @@ static int start_pri(struct zt_pri *pri)
3990 pri->fds[i] = -1;
3991 return -1;
3992 }
3993- pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
3994+ pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
3995 /* Force overlap dial if we're doing GR-303! */
3996 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
3997 pri->overlapdial = 1;
3998@@ -9571,39 +10161,77 @@ static char *complete_span_5(const char
3999
4000 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
4001 {
4002- int myfd;
4003+ int myfd, x, d;
4004+ int span;
4005+
4006+ if (argc < 6)
4007+ return RESULT_SHOWUSAGE;
4008
4009 if (!strncasecmp(argv[1], "set", 3)) {
4010- if (argc < 5)
4011+ if (argc < 7)
4012 return RESULT_SHOWUSAGE;
4013
4014- if (ast_strlen_zero(argv[4]))
4015+ if (!argv[4] || ast_strlen_zero(argv[4]))
4016 return RESULT_SHOWUSAGE;
4017
4018+ if (!argv[5])
4019+ return RESULT_SHOWUSAGE;
4020+
4021+ if (!argv[6] || ast_strlen_zero(argv[6]))
4022+ return RESULT_SHOWUSAGE;
4023+
4024+ span = atoi(argv[6]);
4025+ if ((span < 1) && (span > NUM_SPANS)) {
4026+ return RESULT_SUCCESS;
4027+ }
4028+
4029+
4030 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
4031 if (myfd < 0) {
4032 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
4033 return RESULT_SUCCESS;
4034 }
4035+ for (x=0; x < NUM_SPANS; x++) {
4036+ ast_mutex_lock(&pris[x].lock);
4037
4038- ast_mutex_lock(&pridebugfdlock);
4039-
4040- if (pridebugfd >= 0)
4041- close(pridebugfd);
4042-
4043- pridebugfd = myfd;
4044- ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
4045-
4046- ast_mutex_unlock(&pridebugfdlock);
4047+ if (pris[x].span == span) {
4048+ if (pris[x].debugfd >= 0)
4049+ close(pris[x].debugfd);
4050+ pris[x].debugfd = myfd;
4051+ for (d=0; d < NUM_DCHANS; d++) {
4052+ if (pris[x].dchans[d])
4053+ pri_set_debug_fd(pris[x].dchans[d], myfd);
4054+ }
4055+ }
4056+ ast_mutex_unlock(&pris[x].lock);
4057+ }
4058
4059- ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
4060+ ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
4061 } else {
4062+ if (!argv[5] || ast_strlen_zero(argv[5]))
4063+ return RESULT_SHOWUSAGE;
4064 /* Assume it is unset */
4065- ast_mutex_lock(&pridebugfdlock);
4066- close(pridebugfd);
4067- pridebugfd = -1;
4068- ast_cli(fd, "PRI debug output to file disabled\n");
4069- ast_mutex_unlock(&pridebugfdlock);
4070+ span = atoi(argv[5]);
4071+ if ((span < 1) && (span > NUM_SPANS)) {
4072+ return RESULT_SUCCESS;
4073+ }
4074+
4075+ for (x=0; x < NUM_SPANS; x++) {
4076+ ast_mutex_lock(&pris[x].lock);
4077+
4078+ if (pris[x].span == span) {
4079+ if (pris[x].debugfd >= 0)
4080+ close(pris[x].debugfd);
4081+ pris[x].debugfd = -1;
4082+ for (d=0; d < NUM_DCHANS; d++) {
4083+ if (pris[x].dchans[d])
4084+ pri_set_debug_fd(pris[x].dchans[d], -1);
4085+ }
4086+ }
4087+ ast_mutex_unlock(&pris[x].lock);
4088+ }
4089+
4090+ ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
4091 }
4092
4093 return RESULT_SUCCESS;
4094@@ -9644,6 +10272,7 @@ static int handle_pri_debug(int fd, int
4095
4096
4097
4098+
4099 static int handle_pri_no_debug(int fd, int argc, char *argv[])
4100 {
4101 int span;
4102@@ -9793,10 +10422,6 @@ static int handle_pri_show_debug(int fd,
4103 }
4104
4105 }
4106- ast_mutex_lock(&pridebugfdlock);
4107- if (pridebugfd >= 0)
4108- ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
4109- ast_mutex_unlock(&pridebugfdlock);
4110
4111 if (!count)
4112 ast_cli(fd, "No debug set or no PRI running\n");
4113@@ -9823,6 +10448,18 @@ static const char pri_show_spans_help[]
4114 "Usage: pri show spans\n"
4115 " Displays PRI Information\n";
4116
4117+static char bri_debug_help[] =
4118+ "Usage: bri debug span <span>\n"
4119+ " Enables debugging on a given BRI span\n";
4120+
4121+static char bri_no_debug_help[] =
4122+ "Usage: bri no debug span <span>\n"
4123+ " Disables debugging on a given BRI span\n";
4124+
4125+static char bri_really_debug_help[] =
4126+ "Usage: bri intensive debug span <span>\n"
4127+ " Enables debugging down to the Q.921 level\n";
4128+
4129 static struct ast_cli_entry zap_pri_cli[] = {
4130 { { "pri", "debug", "span", NULL },
4131 handle_pri_debug, "Enables PRI debugging on a span",
4132@@ -9847,6 +10484,15 @@ static struct ast_cli_entry zap_pri_cli[
4133 { { "pri", "show", "debug", NULL },
4134 handle_pri_show_debug, "Displays current PRI debug settings" },
4135
4136+ { { "bri", "debug", "span", NULL }, handle_pri_debug,
4137+ "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
4138+
4139+ { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
4140+ "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
4141+
4142+ { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
4143+ "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
4144+
4145 { { "pri", "set", "debug", "file", NULL },
4146 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
4147
4148@@ -9859,8 +10505,76 @@ static struct ast_cli_entry zap_pri_cli[
4149 #endif
4150 };
4151
4152+static char *zapCD_tdesc = "Call Deflection";
4153+static char *zapCD_app = "zapCD";
4154+static char *zapCD_synopsis = "Call Deflection";
4155+
4156+static int app_zapCD(struct ast_channel *chan, void *data)
4157+{
4158+ struct zt_pvt *p = chan->tech_pvt;
4159+
4160+ if((!p->pri) || (!p->pri->pri)) {
4161+ return -1;
4162+ }
4163+
4164+ if(!data) {
4165+ ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
4166+ return -1;
4167+ }
4168+ return pri_deflect(p->pri->pri, p->call, data);
4169+}
4170+
4171+static char *zapInband_tdesc = "Inband Call Progress (pre-answer)";
4172+static char *zapInband_app = "zapInband";
4173+static char *zapInband_synopsis = "Inband Call Progress";
4174+
4175+static int app_zapInband(struct ast_channel *chan, void *data)
4176+{
4177+ struct zt_pvt *p = chan->tech_pvt;
4178+
4179+ return pri_acknowledge(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1);
4180+}
4181+
4182 #endif /* HAVE_PRI */
4183
4184+static int app_zapEC(struct ast_channel *chan, void *data)
4185+{
4186+ int res=-1;
4187+ struct zt_pvt *p = NULL;
4188+
4189+ if (!data) {
4190+ ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
4191+ }
4192+ if (chan && !strcasecmp("ZAP",chan->tech->type)) {
4193+ p = chan->tech_pvt;
4194+ if (!p) return res;
4195+ if (!strcasecmp("on",(char *)data)) {
4196+ zt_enable_ec(p);
4197+ res = 0;
4198+ if (option_verbose > 3) {
4199+ ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
4200+ }
4201+ } else if (!strcasecmp("off",(char *)data)) {
4202+ zt_disable_ec(p);
4203+ res = 0;
4204+ if (option_verbose > 3) {
4205+ ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
4206+ }
4207+ } else {
4208+ ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
4209+ }
4210+ } else {
4211+ ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
4212+ res = 0;
4213+ }
4214+
4215+ return res;
4216+}
4217+
4218+static char *zapEC_tdesc = "Enable/disable Echo cancelation";
4219+static char *zapEC_app = "zapEC";
4220+static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
4221+
4222 static int zap_destroy_channel(int fd, int argc, char **argv)
4223 {
4224 int channel;
4225@@ -10441,8 +11155,11 @@ static int __unload_module(void)
4226 }
4227 ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
4228 ast_unregister_application(zap_send_keypad_facility_app);
4229+ ast_unregister_application(zapCD_app);
4230+ ast_unregister_application(zapInband_app);
4231 #endif
4232 ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
4233+ ast_unregister_application(zapEC_app);
4234 ast_manager_unregister( "ZapDialOffhook" );
4235 ast_manager_unregister( "ZapHangup" );
4236 ast_manager_unregister( "ZapTransfer" );
4237@@ -10944,6 +11661,22 @@ static int process_zap(struct zt_chan_co
4238 confp->chan.sig = SIG_GR303FXSKS;
4239 confp->chan.radio = 0;
4240 confp->pri.nodetype = PRI_CPE;
4241+ } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
4242+ confp->chan.radio = 0;
4243+ confp->chan.sig = SIG_PRI;
4244+ confp->pri.nodetype = BRI_NETWORK_PTMP;
4245+ } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
4246+ confp->chan.sig = SIG_PRI;
4247+ confp->chan.radio = 0;
4248+ confp->pri.nodetype = BRI_CPE_PTMP;
4249+ } else if (!strcasecmp(v->value, "bri_net")) {
4250+ confp->chan.radio = 0;
4251+ confp->chan.sig = SIG_PRI;
4252+ confp->pri.nodetype = BRI_NETWORK;
4253+ } else if (!strcasecmp(v->value, "bri_cpe")) {
4254+ confp->chan.sig = SIG_PRI;
4255+ confp->chan.radio = 0;
4256+ confp->pri.nodetype = BRI_CPE;
4257 #endif
4258 } else {
4259 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
4260@@ -11056,9 +11789,21 @@ static int process_zap(struct zt_chan_co
4261 confp->chan.priindication_oob = 1;
4262 else if (!strcasecmp(v->value, "inband"))
4263 confp->chan.priindication_oob = 0;
4264+ else if (!strcasecmp(v->value, "passthrough"))
4265+ confp->chan.priindication_oob = 2;
4266 else
4267- ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
4268+ ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband', 'outofband' or 'passthrough' at line %d\n",
4269 v->value, v->lineno);
4270+ } else if (!strcasecmp(v->name, "pritransfer")) {
4271+ if (!strcasecmp(v->value, "no"))
4272+ confp->chan.pritransfer = 0;
4273+ else if (!strcasecmp(v->value, "ect"))
4274+ confp->chan.pritransfer = 1;
4275+ else if (!strcasecmp(v->value, "hangup"))
4276+ confp->chan.pritransfer = 2;
4277+ else
4278+ ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
4279+ v->value, v->lineno);
4280 } else if (!strcasecmp(v->name, "priexclusive")) {
4281 confp->chan.priexclusive = ast_true(v->value);
4282 } else if (!strcasecmp(v->name, "internationalprefix")) {
4283@@ -11071,6 +11816,10 @@ static int process_zap(struct zt_chan_co
4284 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
4285 } else if (!strcasecmp(v->name, "unknownprefix")) {
4286 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
4287+ } else if (!strcasecmp(v->name, "nocid")) {
4288+ ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
4289+ } else if (!strcasecmp(v->name, "withheldcid")) {
4290+ ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
4291 } else if (!strcasecmp(v->name, "resetinterval")) {
4292 if (!strcasecmp(v->value, "never"))
4293 confp->pri.resetinterval = -1;
4294@@ -11087,6 +11836,8 @@ static int process_zap(struct zt_chan_co
4295 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
4296 } else if (!strcasecmp(v->name, "idledial")) {
4297 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
4298+ } else if (!strcasecmp(v->name, "pritrustusercid")) {
4299+ confp->pri.usercid = ast_true(v->value);
4300 } else if (!strcasecmp(v->name, "overlapdial")) {
4301 confp->pri.overlapdial = ast_true(v->value);
4302 } else if (!strcasecmp(v->name, "pritimer")) {
4303@@ -11389,6 +12140,7 @@ static int setup_zap(int reload)
4304 #ifdef HAVE_PRI
4305 if (!reload) {
4306 for (x = 0; x < NUM_SPANS; x++) {
4307+ pris[x].debugfd = -1;
4308 if (pris[x].pvts[0]) {
4309 if (start_pri(pris + x)) {
4310 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
4311@@ -11436,7 +12188,10 @@ static int load_module(void)
4312 ast_string_field_init(&inuse, 16);
4313 ast_string_field_set(&inuse, name, "GR-303InUse");
4314 ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
4315+ ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
4316+ ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
4317 #endif
4318+ ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
4319 ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
4320
4321 memset(round_robin, 0, sizeof(round_robin));
4322@@ -11470,6 +12225,7 @@ static int zt_sendtext(struct ast_channe
4323 float scont = 0.0;
4324 int index;
4325
4326+
4327 index = zt_get_index(c, p, 0);
4328 if (index < 0) {
4329 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
4330--- a/configs/zapata.conf.sample
4331+++ b/configs/zapata.conf.sample
4332@@ -123,9 +123,20 @@ switchtype=national
4333 ;
4334 ; outofband: Signal Busy/Congestion out of band with RELEASE/DISCONNECT
4335 ; inband: Signal Busy/Congestion using in-band tones
4336+; passthrough: Listen to the telco
4337 ;
4338 ; priindication = outofband
4339 ;
4340+; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
4341+;
4342+; Configure how transfers are initiated. ECT should be preferred
4343+;
4344+; no: no transfers allowed (results in hangup)
4345+; ect: use ECT (facility)
4346+; hangup: transfer on hangup (if your phones dont support ECT)
4347+;
4348+; pritransfer = ect
4349+;
4350 ; If you need to override the existing channels selection routine and force all
4351 ; PRI channels to be marked as exclusively selected, set this to yes.
4352 ; priexclusive = yes
4353Change the ABI of ast_channel_tech to add a new function, send_message that is
4354to be used by channels wanting to send text messages with a destination number
4355(mainly GSM).
4356
4357--- a/include/asterisk/channel.h
4358+++ b/include/asterisk/channel.h
4359@@ -247,6 +247,11 @@ struct ast_channel_tech {
4360 /*! \brief Display or transmit text */
4361 int (* const send_text)(struct ast_channel *chan, const char *text);
4362
4363+#if 0 /* we (Debian) disable that addition because of ABI breakage */
4364+ /*! \brief send a message */
4365+ int (* const send_message)(struct ast_channel *chan, const char *dest, const char *text, int ispdu);
4366+#endif
4367+
4368 /*! \brief Display or send an image */
4369 int (* const send_image)(struct ast_channel *chan, struct ast_frame *frame);
4370
4371@@ -689,6 +694,16 @@ struct ast_channel *ast_request_and_dial
4372
4373 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);
4374
4375+/*! \brief "Requests" a channel for sending a message
4376+ * \param type type of channel to request
4377+ * \param data data to pass to the channel requester
4378+ * \param status status
4379+ * Request a channel of a given type, with data as optional information used
4380+ * by the low level module
4381+ * \return Returns 0 on success, -1 on failure.
4382+ */
4383+int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu);
4384+
4385 /*!\brief Register a channel technology (a new channel driver)
4386 * Called by a channel module to register the kind of channels it supports.
4387 * \param tech Structure defining channel technology or "type"
4388@@ -910,6 +925,16 @@ int ast_set_write_format(struct ast_chan
4389 */
4390 int ast_sendtext(struct ast_channel *chan, const char *text);
4391
4392+/*! \brief Sends message to a channel
4393+ * Write text to a display on a channel
4394+ * \param chan channel to act upon
4395+ * \param dest destination number/user
4396+ * \param text string of text to send on the channel
4397+ * \param ispdu message is in PDU format
4398+ * \return Returns 0 on success, -1 on failure
4399+ */
4400+int ast_sendmessage(struct ast_channel *chan, const char *dest, const char *text, int ispdu);
4401+
4402 /*! \brief Receives a text character from a channel
4403 * \param chan channel to act upon
4404 * \param timeout timeout in milliseconds (0 for infinite wait)
4405--- a/main/channel.c
4406+++ b/main/channel.c
4407@@ -2472,6 +2472,21 @@ int ast_sendtext(struct ast_channel *cha
4408 return res;
4409 }
4410
4411+int ast_sendmessage(struct ast_channel *chan, const char *dest, const char *text, int ispdu)
4412+{
4413+ int res = 0;
4414+ /* Stop if we're a zombie or need a soft hangup */
4415+ if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))
4416+ return -1;
4417+ CHECK_BLOCKING(chan);
4418+#if 0 /* we (Debian) disable that addition because of ABI breakage */
4419+ if (chan->tech->send_message)
4420+ res = chan->tech->send_message(chan, dest, text, ispdu);
4421+#endif
4422+ ast_clear_flag(chan, AST_FLAG_BLOCKING);
4423+ return res;
4424+}
4425+
4426 int ast_senddigit_begin(struct ast_channel *chan, char digit)
4427 {
4428 /* Device does not support DTMF tones, lets fake
4429@@ -4515,6 +4530,25 @@ void ast_channel_stop_silence_generator(
4430 }
4431
4432
4433+int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu) {
4434+ struct ast_channel *chan = NULL;
4435+ int status;
4436+ int res = -1;
4437+
4438+ chan = ast_request(type, AST_FORMAT_SLINEAR, data, &status);
4439+ if (chan) {
4440+ if (from) {
4441+ ast_set_callerid(chan, from, from, from);
4442+ }
4443+ res = ast_sendmessage(chan, to, message, ispdu);
4444+ /* XXX what about message CDRs ??? XXX */
4445+ ast_hangup(chan);
4446+ return res;
4447+ }
4448+
4449+ return res;
4450+}
4451+
4452 /*! \ brief Convert channel reloadreason (ENUM) to text string for manager event */
4453 const char *channelreloadreason2txt(enum channelreloadreason reason)
4454 {
4455--- a/main/manager.c
4456+++ b/main/manager.c
4457@@ -11,6 +11,9 @@
4458 * the project provides a web site, mailing lists and IRC
4459 * channels for your use.
4460 *
4461+ * Copyright (C) 2003-2004, Junghanns.NET Gmbh
4462+ * Klaus-Peter Junghanns <kpj@junghanns.net>
4463+ *
4464 * This program is free software, distributed under the terms of
4465 * the GNU General Public License Version 2. See the LICENSE file
4466 * at the top of the source tree.
4467@@ -1427,6 +1430,49 @@ static int action_hangup(struct mansessi
4468 return 0;
4469 }
4470
4471+static char mandescr_message[] =
4472+"Description: Send a message\n"
4473+"Variables: \n"
4474+" Channel: The destination channel(e.g. SIP/phone1)\n"
4475+" From: \n"
4476+" Message: The message to send\n";
4477+
4478+static int action_message(struct mansession *s, const struct message *m)
4479+{
4480+ const char *name = astman_get_header(m, "Channel");
4481+ const char *from = astman_get_header(m, "From");
4482+ const char *message = astman_get_header(m, "Message");
4483+ const char *pdu = astman_get_header(m, "PDU");
4484+ char tmp[256];
4485+ char *tech, *data;
4486+ int res;
4487+ if (ast_strlen_zero(name) || (ast_strlen_zero(message) && ast_strlen_zero(pdu))) {
4488+ astman_send_error(s, m, "No channel or message/PDU specified");
4489+ return 0;
4490+ }
4491+ ast_copy_string(tmp, name, sizeof(tmp));
4492+ tech = tmp;
4493+ data = strchr(tmp, '/');
4494+ if (!data) {
4495+ astman_send_error(s, m, "Invalid channel\n");
4496+ return 0;
4497+ }
4498+ *data = '\0';
4499+ data++;
4500+ if (ast_strlen_zero(pdu)) {
4501+ res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)message, 0);
4502+ } else {
4503+ res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)pdu, 1);
4504+ }
4505+
4506+ if (res) {
4507+ astman_send_error(s, m, "Error sending message");
4508+ return 0;
4509+ }
4510+ astman_send_ack(s, m, "Message sent");
4511+ return 0;
4512+}
4513+
4514 static char mandescr_setvar[] =
4515 "Description: Set a global or local channel variable.\n"
4516 "Variables: (Names marked with * are required)\n"
4517@@ -2853,6 +2899,7 @@ int init_manager(void)
4518 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
4519 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
4520 ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
4521+ ast_manager_register2("Message", EVENT_FLAG_CALL, action_message, "Send Message", mandescr_message);
4522 ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
4523 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
4524 ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
4525--- a/pbx/pbx_spool.c
4526+++ b/pbx/pbx_spool.c
4527@@ -87,6 +87,10 @@ struct outgoing {
4528 char app[256];
4529 char data[256];
4530
4531+ /* If SMS */
4532+ char message[256];
4533+ char pdu[256];
4534+
4535 /* If extension/context/priority */
4536 char exten[256];
4537 char context[256];
4538@@ -181,6 +185,10 @@ static int apply_outgoing(struct outgoin
4539 ast_copy_string(o->app, c, sizeof(o->app));
4540 } else if (!strcasecmp(buf, "data")) {
4541 ast_copy_string(o->data, c, sizeof(o->data));
4542+ } else if (!strcasecmp(buf, "message")) {
4543+ strncpy(o->message, c, sizeof(o->message) - 1);
4544+ } else if (!strcasecmp(buf, "pdu")) {
4545+ strncpy(o->pdu, c, sizeof(o->pdu) - 1);
4546 } else if (!strcasecmp(buf, "maxretries")) {
4547 if (sscanf(c, "%d", &o->maxretries) != 1) {
4548 ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn);
4549@@ -241,8 +249,8 @@ static int apply_outgoing(struct outgoin
4550 }
4551 }
4552 ast_copy_string(o->fn, fn, sizeof(o->fn));
4553- if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) {
4554- ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
4555+ if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || ((ast_strlen_zero(o->app) && ast_strlen_zero(o->exten) && ast_strlen_zero(o->message) && ast_strlen_zero(o->pdu)))) {
4556+ ast_log(LOG_WARNING, "At least one of app or extension (or keyword message/pdu)must be specified, along with tech and dest in file %s\n", fn);
4557 return -1;
4558 }
4559 return 0;
4560@@ -332,6 +340,14 @@ static void *attempt_thread(void *data)
4561 if (option_verbose > 2)
4562 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);
4563 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);
4564+ } else if (!ast_strlen_zero(o->message)) {
4565+ if (option_verbose > 2)
4566+ ast_verbose(VERBOSE_PREFIX_3 "Attempting to send message on %s/%s (Retry %d)\n", o->tech, o->dest, o->retries);
4567+ res = ast_send_message(o->tech, o->dest, o->dest, (ast_strlen_zero(o->cid_name) ? o->cid_num : o->cid_name), o->message, 0);
4568+ } else if (!ast_strlen_zero(o->pdu)) {
4569+ if (option_verbose > 2)
4570+ ast_verbose(VERBOSE_PREFIX_3 "Attempting to send message in PDU format on %s/%s (Retry %d)\n", o->tech, o->dest, o->retries);
4571+ res = ast_send_message(o->tech, o->dest, o->dest, (ast_strlen_zero(o->cid_name) ? o->cid_num : o->cid_name), o->pdu, 1);
4572 } else {
4573 if (option_verbose > 2)
4574 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);
4575@@ -348,9 +364,14 @@ static void *attempt_thread(void *data)
4576 safe_append(o, time(NULL), "EndRetry");
4577 }
4578 } else {
4579+ if (!ast_strlen_zero(o->message)) {
4580+ if (option_verbose > 2)
4581+ ast_verbose(VERBOSE_PREFIX_2 "Message sent to %s/%s\n", o->tech, o->dest);
4582+ } else {
4583 ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
4584 ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
4585- remove_from_queue(o, "Completed");
4586+ }
4587+ remove_from_queue(o, "Completed");
4588 }
4589 free_outgoing(o);
4590 return NULL;
4591--- a/include/asterisk/monitor.h
4592+++ b/include/asterisk/monitor.h
4593@@ -38,6 +38,8 @@ struct ast_channel_monitor {
4594 char write_filename[FILENAME_MAX];
4595 char filename_base[FILENAME_MAX];
4596 int filename_changed;
4597+ char target_url[FILENAME_MAX];
4598+ char target_script[FILENAME_MAX];
4599 char *format;
4600 int joinfiles;
4601 enum AST_MONITORING_STATE state;
4602@@ -46,7 +48,7 @@ struct ast_channel_monitor {
4603
4604 /* Start monitoring a channel */
4605 int ast_monitor_start(struct ast_channel *chan, const char *format_spec,
4606- const char *fname_base, int need_lock );
4607+ const char *fname_base, const char *target_url, const char *target_script, int need_lock );
4608
4609 /* Stop monitoring a channel */
4610 int ast_monitor_stop(struct ast_channel *chan, int need_lock);
4611--- a/res/res_monitor.c
4612+++ b/res/res_monitor.c
4613@@ -130,7 +130,7 @@ static int ast_monitor_set_state(struct
4614
4615 /* Start monitoring a channel */
4616 int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
4617- const char *fname_base, int need_lock)
4618+ const char *fname_base, const char *target_url, const char *target_script, int need_lock)
4619 {
4620 int res = 0;
4621 char tmp[256];
4622@@ -154,6 +154,11 @@ int ast_monitor_start( struct ast_channe
4623 return -1;
4624 }
4625
4626+ if (target_url)
4627+ ast_copy_string(monitor->target_url, target_url, sizeof(monitor->target_url));
4628+ if (target_script)
4629+ ast_copy_string(monitor->target_script, target_script, sizeof(monitor->target_script));
4630+
4631 /* Determine file names */
4632 if (!ast_strlen_zero(fname_base)) {
4633 int directory = strchr(fname_base, '/') ? 1 : 0;
4634@@ -297,6 +302,8 @@ int ast_monitor_stop(struct ast_channel
4635 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
4636 char tmp[1024];
4637 char tmp2[1024];
4638+ char tmp3[1024];
4639+ int result;
4640 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
4641 char *name = chan->monitor->filename_base;
4642 int directory = strchr(name, '/') ? 1 : 0;
4643@@ -325,8 +332,13 @@ int ast_monitor_stop(struct ast_channel
4644 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name); /* remove legs when done mixing */
4645 ast_copy_string(tmp, tmp2, sizeof(tmp));
4646 }
4647- ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
4648- if (ast_safe_system(tmp) == -1)
4649+ if (!ast_strlen_zero(chan->monitor->target_script) && !ast_strlen_zero(chan->monitor->target_url)) {
4650+ snprintf(tmp3,sizeof(tmp3), "( %s& nice -19 %s \"%s/%s.%s\" \"%s\" ) &",tmp, chan->monitor->target_script , dir, name, format, chan->monitor->target_url);
4651+ ast_copy_string(tmp, tmp3, sizeof(tmp));
4652+ }
4653+ ast_log(LOG_NOTICE,"monitor executing %s\n",tmp);
4654+ result = ast_safe_system(tmp);
4655+ if (result == -1)
4656 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
4657 }
4658
4659@@ -467,7 +479,7 @@ static int start_monitor_exec(struct ast
4660 return 0;
4661 }
4662
4663- res = ast_monitor_start(chan, format, fname_base, 1);
4664+ res = ast_monitor_start(chan, format, fname_base, NULL, NULL, 1);
4665 if (res < 0)
4666 res = ast_monitor_change_fname(chan, fname_base, 1);
4667 ast_monitor_setjoinfiles(chan, joinfiles);
4668@@ -506,6 +518,8 @@ static int start_monitor_action(struct m
4669 const char *fname = astman_get_header(m, "File");
4670 const char *format = astman_get_header(m, "Format");
4671 const char *mix = astman_get_header(m, "Mix");
4672+ const char *target_url = astman_get_header(m, "TargetURL");
4673+ const char *target_script = astman_get_header(m, "TargetScript");
4674 char *d;
4675
4676 if (ast_strlen_zero(name)) {
4677@@ -530,7 +544,7 @@ static int start_monitor_action(struct m
4678 *d = '-';
4679 }
4680
4681- if (ast_monitor_start(c, format, fname, 1)) {
4682+ if (ast_monitor_start(c, format, fname, target_url, target_script, 1)) {
4683 if (ast_monitor_change_fname(c, fname, 1)) {
4684 astman_send_error(s, m, "Could not start monitoring channel");
4685 ast_channel_unlock(c);
4686--- a/apps/app_queue.c
4687+++ b/apps/app_queue.c
4688@@ -2891,13 +2891,13 @@ static int try_calling(struct queue_ent
4689 else
4690 which = peer;
4691 if (monitorfilename)
4692- ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
4693+ ast_monitor_start(which, qe->parent->monfmt, monitorfilename, NULL, NULL, 1 );
4694 else if (qe->chan->cdr)
4695- ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
4696+ ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, NULL, NULL, 1 );
4697 else {
4698 /* Last ditch effort -- no CDR, make up something */
4699 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
4700- ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
4701+ ast_monitor_start(which, qe->parent->monfmt, tmpid, NULL, NULL, 1 );
4702 }
4703 if (qe->parent->monjoin)
4704 ast_monitor_setjoinfiles(which, 1);
4705--- a/channels/chan_agent.c
4706+++ b/channels/chan_agent.c
4707@@ -419,7 +419,7 @@ static int __agent_start_monitoring(stru
4708 if ((pointer = strchr(filename, '.')))
4709 *pointer = '-';
4710 snprintf(tmp, sizeof(tmp), "%s%s", savecallsin, filename);
4711- ast_monitor_start(ast, recordformat, tmp, needlock);
4712+ ast_monitor_start(ast, recordformat, tmp, NULL, NULL, needlock);
4713 ast_monitor_setjoinfiles(ast, 1);
4714 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix, filename, recordformatext);
4715 #if 0
4716--- a/include/asterisk/devicestate.h
4717+++ b/include/asterisk/devicestate.h
4718@@ -47,7 +47,7 @@ extern "C" {
4719 #define AST_DEVICE_ONHOLD 8
4720
4721 /*! \brief Devicestate watcher call back */
4722-typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
4723+typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data, char *cid_num, char *cid_name);
4724
4725 /*! \brief Devicestate provider call back */
4726 typedef int (*ast_devstate_prov_cb_type)(const char *data);
4727@@ -92,7 +92,7 @@ int ast_device_state_changed(const char
4728 * callbacks for the changed extensions
4729 * Returns 0 on success, -1 on failure
4730 */
4731-int ast_device_state_changed_literal(const char *device);
4732+int ast_device_state_changed_literal(const char *device, const char *cid_num, const char *cid_name);
4733
4734 /*! \brief Registers a device state change callback
4735 * \param callback Callback
4736--- a/main/devicestate.c
4737+++ b/main/devicestate.c
4738@@ -78,6 +78,8 @@ static AST_LIST_HEAD_STATIC(devstate_cbs
4739
4740 struct state_change {
4741 AST_LIST_ENTRY(state_change) list;
4742+ char cid_num[AST_MAX_EXTENSION];
4743+ char cid_name[AST_MAX_EXTENSION];
4744 char device[1];
4745 };
4746
4747@@ -277,7 +279,7 @@ void ast_devstate_del(ast_devstate_cb_ty
4748 /*! \brief Notify callback watchers of change, and notify PBX core for hint updates
4749 Normally executed within a separate thread
4750 */
4751-static void do_state_change(const char *device)
4752+static void do_state_change(const char *device, char *cid_num, char *cid_name)
4753 {
4754 int state;
4755 struct devstate_cb *devcb;
4756@@ -288,13 +290,13 @@ static void do_state_change(const char *
4757
4758 AST_LIST_LOCK(&devstate_cbs);
4759 AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
4760- devcb->callback(device, state, devcb->data);
4761+ devcb->callback(device, state, devcb->data, cid_num, cid_name);
4762 AST_LIST_UNLOCK(&devstate_cbs);
4763
4764- ast_hint_state_changed(device);
4765+ ast_hint_state_changed(device, cid_num, cid_name);
4766 }
4767
4768-static int __ast_device_state_changed_literal(char *buf, int norecurse)
4769+static int __ast_device_state_changed_literal(char *buf, int norecurse, char *cid_num, char *cid_name)
4770 {
4771 char *device;
4772 struct state_change *change;
4773@@ -308,10 +310,16 @@ static int __ast_device_state_changed_li
4774 if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
4775 /* we could not allocate a change struct, or */
4776 /* there is no background thread, so process the change now */
4777- do_state_change(device);
4778+ do_state_change(device, cid_num, cid_name);
4779 } else {
4780 /* queue the change */
4781 strcpy(change->device, device);
4782+ if (cid_num && (!ast_strlen_zero(cid_num))) {
4783+ strncpy(change->cid_num, cid_num, sizeof(change->cid_num) - 1);
4784+ }
4785+ if (cid_name && (!ast_strlen_zero(cid_name))) {
4786+ strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
4787+ }
4788 AST_LIST_LOCK(&state_changes);
4789 AST_LIST_INSERT_TAIL(&state_changes, change, list);
4790 if (AST_LIST_FIRST(&state_changes) == change)
4791@@ -329,17 +337,23 @@ static int __ast_device_state_changed_li
4792 */
4793 if (!norecurse && (tmp = strrchr(device, '-'))) {
4794 *tmp = '\0';
4795- __ast_device_state_changed_literal(device, 1);
4796+ __ast_device_state_changed_literal(device, 1, cid_num, cid_name);
4797 }
4798
4799 return 1;
4800 }
4801
4802-int ast_device_state_changed_literal(const char *dev)
4803+int ast_device_state_changed_literal(const char *dev, const char *cid_num, const char *cid_name)
4804 {
4805 char *buf;
4806+ char *buf2 = NULL;
4807+ char *buf3 = NULL;
4808 buf = ast_strdupa(dev);
4809- return __ast_device_state_changed_literal(buf, 0);
4810+ if (cid_num)
4811+ buf2 = ast_strdupa(cid_num);
4812+ if (cid_name)
4813+ buf3 = ast_strdupa(cid_name);
4814+ return __ast_device_state_changed_literal(buf, 0, buf2, buf3);
4815 }
4816
4817 /*! \brief Accept change notification, add it to change queue */
4818@@ -351,7 +365,7 @@ int ast_device_state_changed(const char
4819 va_start(ap, fmt);
4820 vsnprintf(buf, sizeof(buf), fmt, ap);
4821 va_end(ap);
4822- return __ast_device_state_changed_literal(buf, 0);
4823+ return __ast_device_state_changed_literal(buf, 0, NULL, NULL);
4824 }
4825
4826 /*! \brief Go through the dev state change queue and update changes in the dev state thread */
4827@@ -366,7 +380,7 @@ static void *do_devstate_changes(void *d
4828 if (cur) {
4829 /* we got an entry, so unlock the list while we process it */
4830 AST_LIST_UNLOCK(&state_changes);
4831- do_state_change(cur->device);
4832+ do_state_change(cur->device, cur->cid_num, cur->cid_name);
4833 free(cur);
4834 AST_LIST_LOCK(&state_changes);
4835 } else {
4836--- a/include/asterisk/channel.h
4837+++ b/include/asterisk/channel.h
4838@@ -613,8 +613,13 @@ int ast_channel_datastore_remove(struct
4839 /*! \brief Find a datastore on a channel */
4840 struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, char *uid);
4841
4842+extern ast_mutex_t uniquelock;
4843+
4844+/*! \brief Change the state of a channel and the callerid of the calling channel*/
4845+int ast_setstate_and_callerid(struct ast_channel *chan, enum ast_channel_state state, char *cid_num, char *cid_name);
4846+
4847 /*! \brief Change the state of a channel */
4848-int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
4849+int ast_setstate(struct ast_channel *chan, enum ast_channel_state state);
4850
4851 /*! \brief Create a channel structure
4852 \return Returns NULL on failure to allocate.
4853--- a/main/channel.c
4854+++ b/main/channel.c
4855@@ -1261,7 +1261,7 @@ void ast_channel_free(struct ast_channel
4856 free(chan);
4857 AST_LIST_UNLOCK(&channels);
4858
4859- ast_device_state_changed_literal(name);
4860+ ast_device_state_changed_literal(name, NULL, NULL);
4861 }
4862
4863 struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, char *uid)
4864@@ -3673,7 +3673,7 @@ void ast_set_callerid(struct ast_channel
4865 ast_channel_unlock(chan);
4866 }
4867
4868-int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
4869+int ast_setstate_and_callerid(struct ast_channel *chan, enum ast_channel_state state, char *cid_num, char *cid_name)
4870 {
4871 int oldstate = chan->_state;
4872
4873@@ -3681,7 +3681,7 @@ int ast_setstate(struct ast_channel *cha
4874 return 0;
4875
4876 chan->_state = state;
4877- ast_device_state_changed_literal(chan->name);
4878+ ast_device_state_changed_literal(chan->name, cid_num, cid_name);
4879 /* setstate used to conditionally report Newchannel; this is no more */
4880 manager_event(EVENT_FLAG_CALL,
4881 "Newstate",
4882@@ -3698,6 +3698,11 @@ int ast_setstate(struct ast_channel *cha
4883 return 0;
4884 }
4885
4886+int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
4887+{
4888+ return ast_setstate_and_callerid(chan, state, NULL, NULL);
4889+}
4890+
4891 /*! \brief Find bridged channel */
4892 struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
4893 {
4894--- a/include/asterisk/pbx.h
4895+++ b/include/asterisk/pbx.h
4896@@ -63,7 +63,7 @@ struct ast_ignorepat;
4897 struct ast_sw;
4898
4899 /*! \brief Typedef for devicestate and hint callbacks */
4900-typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
4901+typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data, char *cid_num, char *cid_name);
4902
4903 /*! \brief Data structure associated with a custom dialplan function */
4904 struct ast_custom_function {
4905@@ -875,7 +875,7 @@ int ast_func_read(struct ast_channel *ch
4906 */
4907 int ast_func_write(struct ast_channel *chan, char *function, const char *value);
4908
4909-void ast_hint_state_changed(const char *device);
4910+void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name);
4911
4912 #if defined(__cplusplus) || defined(c_plusplus)
4913 }
4914--- a/main/pbx.c
4915+++ b/main/pbx.c
4916@@ -2022,7 +2022,7 @@ int ast_extension_state(struct ast_chann
4917 return ast_extension_state2(e); /* Check all devices in the hint */
4918 }
4919
4920-void ast_hint_state_changed(const char *device)
4921+void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
4922 {
4923 struct ast_hint *hint;
4924
4925@@ -2053,11 +2053,11 @@ void ast_hint_state_changed(const char *
4926
4927 /* For general callbacks */
4928 for (cblist = statecbs; cblist; cblist = cblist->next)
4929- cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
4930+ cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
4931
4932 /* For extension callbacks */
4933 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
4934- cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
4935+ cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
4936
4937 hint->laststate = state; /* record we saw the change */
4938 }
4939@@ -2252,7 +2252,7 @@ static int ast_remove_hint(struct ast_ex
4940 /* Notify with -1 and remove all callbacks */
4941 cbprev = cblist;
4942 cblist = cblist->next;
4943- cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
4944+ cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
4945 free(cbprev);
4946 }
4947 hint->callbacks = NULL;
4948@@ -4021,7 +4021,7 @@ void ast_merge_contexts_and_delete(struc
4949 while (thiscb) {
4950 prevcb = thiscb;
4951 thiscb = thiscb->next;
4952- prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
4953+ prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
4954 free(prevcb);
4955 }
4956 } else {
4957--- a/channels/chan_sip.c
4958+++ b/channels/chan_sip.c
4959@@ -1342,7 +1342,7 @@ static void ast_quiet_chan(struct ast_ch
4960 static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
4961
4962 /*--- Device monitoring and Device/extension state handling */
4963-static int cb_extensionstate(char *context, char* exten, int state, void *data);
4964+static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name);
4965 static int sip_devicestate(void *data);
4966 static int sip_poke_noanswer(const void *data);
4967 static int sip_poke_peer(struct sip_peer *peer);
4968@@ -8593,7 +8593,7 @@ static void sip_peer_hold(struct sip_pvt
4969 /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
4970 \note If you add an "hint" priority to the extension in the dial plan,
4971 you will get notifications on device state changes */
4972-static int cb_extensionstate(char *context, char* exten, int state, void *data)
4973+static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
4974 {
4975 struct sip_pvt *p = data;
4976
4977@@ -12783,7 +12783,7 @@ static void handle_response(struct sip_p
4978 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
4979 /* Ready to send the next state we have on queue */
4980 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
4981- cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
4982+ cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p, NULL, NULL);
4983 }
4984 }
4985 } else if (sipmethod == SIP_REGISTER)
4986@@ -13036,7 +13036,7 @@ static void handle_response(struct sip_p
4987 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
4988 /* Ready to send the next state we have on queue */
4989 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
4990- cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
4991+ cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p, NULL, NULL);
4992 }
4993 }
4994 } else if (sipmethod == SIP_BYE)
4995--- a/apps/app_queue.c
4996+++ b/apps/app_queue.c
4997@@ -721,7 +721,7 @@ static void *device_state_thread(void *d
4998 return NULL;
4999 }
5000 /*! \brief Producer of the statechange queue */
5001-static int statechange_queue(const char *dev, int state, void *ign)
5002+static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
5003 {
5004 struct statechange *sc;
5005
5006--- a/include/asterisk/manager.h
5007+++ b/include/asterisk/manager.h
5008@@ -55,6 +55,7 @@
5009 #define EVENT_FLAG_AGENT (1 << 5) /* Ability to read/set agent info */
5010 #define EVENT_FLAG_USER (1 << 6) /* Ability to read/set user info */
5011 #define EVENT_FLAG_CONFIG (1 << 7) /* Ability to modify configurations */
5012+#define EVENT_FLAG_EXTENSIONSTATUS (1 << 8) /* ExtensionStatus events */
5013
5014 /* Export manager structures */
5015 #define AST_MAX_MANHEADERS 128
5016--- a/main/manager.c
5017+++ b/main/manager.c
5018@@ -129,6 +129,7 @@ static struct permalias {
5019 { EVENT_FLAG_AGENT, "agent" },
5020 { EVENT_FLAG_USER, "user" },
5021 { EVENT_FLAG_CONFIG, "config" },
5022+ { EVENT_FLAG_EXTENSIONSTATUS, "extensionstatus" },
5023 { -1, "all" },
5024 { 0, "none" },
5025 };
5026@@ -2551,10 +2552,12 @@ int ast_manager_unregister(char *action)
5027 return 0;
5028 }
5029
5030-static int manager_state_cb(char *context, char *exten, int state, void *data)
5031+static int manager_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
5032 {
5033+ char hint[256] = "";
5034+ ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
5035 /* Notify managers of change */
5036- manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
5037+ 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);
5038 return 0;
5039 }
5040
5041--- a/apps/app_devstate.c
5042+++ b/apps/app_devstate.c
5043@@ -50,7 +50,7 @@ static struct ast_cli_entry cli_dev_sta
5044 static int devstate_cli(int fd, int argc, char *argv[])
5045 {
5046 char devName[128];
5047- if (argc != 3)
5048+ if ((argc != 3) && (argc != 4) && (argc != 5))
5049 return RESULT_SHOWUSAGE;
5050
5051 if (ast_db_put("DEVSTATES", argv[1], argv[2]))
5052@@ -58,7 +58,15 @@ static int devstate_cli(int fd, int argc
5053 ast_log(LOG_DEBUG, "ast_db_put failed\n");
5054 }
5055 snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
5056- ast_device_state_changed_literal(devName);
5057+ if (argc == 4) {
5058+ ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
5059+ ast_device_state_changed_literal(devName, argv[3], NULL);
5060+ } else if (argc == 5) {
5061+ ast_log(LOG_NOTICE, "devname %s cid %s cidname %s\n", devName, argv[3], argv[4]);
5062+ ast_device_state_changed_literal(devName, argv[3], argv[4]);
5063+ } else {
5064+ ast_device_state_changed_literal(devName, NULL, NULL);
5065+ }
5066 return RESULT_SUCCESS;
5067 }
5068
5069@@ -93,7 +101,7 @@ static int devstate_exec(struct ast_chan
5070 }
5071
5072 snprintf(devName, sizeof(devName), "DS/%s", device);
5073- ast_device_state_changed_literal(devName);
5074+ ast_device_state_changed_literal(devName, NULL, NULL);
5075
5076 ast_module_user_remove(u);
5077 return 0;
5078@@ -150,6 +158,8 @@ static int action_devstate(struct manses
5079 const char *devstate = astman_get_header(m, "Devstate");
5080 const char *value = astman_get_header(m, "Value");
5081 const char *id = astman_get_header(m,"ActionID");
5082+ const char *cid_num = astman_get_header(m, "CallerID");
5083+ const char *cid_name = astman_get_header(m, "CallerIDName");
5084 char devName[128];
5085 char idText[256] = "";
5086
5087@@ -166,7 +176,7 @@ static int action_devstate(struct manses
5088
5089 if (!ast_db_put("DEVSTATES", devstate, (char *)value)) {
5090 snprintf(devName, sizeof(devName), "DS/%s", devstate);
5091- ast_device_state_changed_literal(devName);
5092+ ast_device_state_changed_literal(devName, cid_num, cid_name);
5093 astman_append(s, "Response: Success\r\n%s\r\n", idText);
5094 } else {
5095 ast_log(LOG_DEBUG, "ast_db_put failed\n");
5096--- a/res/res_esel.c
5097+++ b/res/res_esel.c
5098@@ -51,6 +51,8 @@ typedef struct esel_extension_state {
5099 char context[AST_MAX_EXTENSION];
5100 char exten[AST_MAX_EXTENSION];
5101 int state;
5102+ char cid_num[AST_MAX_EXTENSION];
5103+ char cid_name[AST_MAX_EXTENSION];
5104 char devstate[AST_MAX_EXTENSION];
5105 struct esel_extension_state *next;
5106 struct esel_extension_state *prev;
5107@@ -93,7 +95,7 @@ typedef struct esel_pvt {
5108
5109 static struct esel_pvt *donkeys = NULL;
5110
5111-static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data) {
5112+static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data, char *cid_num, char *cid_name) {
5113 struct esel_extension_state *exstate = NULL;
5114
5115 exstate = malloc(sizeof(struct esel_extension_state));
5116@@ -115,6 +117,8 @@ static int esel_queue_extension_state(st
5117 }
5118 ast_copy_string(exstate->exten, exten, sizeof(exstate->exten));
5119 ast_copy_string(exstate->context, context, sizeof(exstate->context));
5120+ ast_copy_string(exstate->cid_num, cid_num, sizeof(exstate->cid_num));
5121+ ast_copy_string(exstate->cid_name, cid_name, sizeof(exstate->cid_name));
5122 exstate->state = state;
5123 if (!queue->head) {
5124 /* Empty queue */
5125@@ -161,7 +165,7 @@ static void esel_export_to_remote(struct
5126 char msg[1024];
5127 int sent = 0;
5128 memset(msg, 0x0, sizeof(msg));
5129- snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state));
5130+ snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\nCallerID: %s\r\nCallerIDName: %s\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state), exstate->cid_num, exstate->cid_name);
5131 sent = send(esel->sockfd, msg, strlen(msg), 0);
5132 if (sent == -1) {
5133 esel->connected = 0;
5134@@ -250,13 +254,13 @@ static void *do_esel_thread(void *data)
5135 return NULL;
5136 }
5137
5138-static int esel_state_cb(char *context, char *exten, int state, void *data) {
5139+static int esel_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name) {
5140 struct esel_pvt *esel;
5141
5142 esel = donkeys;
5143 ast_mutex_lock(&listlock);
5144 while (esel) {
5145- esel_queue_extension_state(&esel->queue, context, exten, state, data);
5146+ esel_queue_extension_state(&esel->queue, context, exten, state, data, cid_num, cid_name);
5147 esel = esel->next;
5148 }
5149 ast_mutex_unlock(&listlock);
5150Add or convert channel operations so they can use the unique ID.
5151
5152--- a/include/asterisk/channel.h
5153+++ b/include/asterisk/channel.h
5154@@ -682,6 +682,18 @@ void ast_channel_free(struct ast_channe
5155 */
5156 struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
5157
5158+/*! \brief Requests a channel
5159+ * \param type type of channel to request
5160+ * \param format requested channel format (codec)
5161+ * \param data data to pass to the channel requester
5162+ * \param status status
5163+ * \param uniqueid uniqueid
5164+ * Request a channel of a given type, with data as optional information used
5165+ * by the low level module. Sets the channels uniqueid to 'uniqueid'.
5166+ * \return Returns an ast_channel on success, NULL on failure.
5167+ */
5168+struct ast_channel *ast_request_with_uniqueid(const char *type, int format, void *data, int *status, char *uniqueid);
5169+
5170 /*!
5171 * \brief Request a channel of a given type, with data as optional information used
5172 * by the low level module and attempt to place a call on it
5173@@ -697,8 +709,12 @@ struct ast_channel *ast_request(const ch
5174 */
5175 struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname);
5176
5177+struct ast_channel *ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, char *uniqueid);
5178+
5179 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);
5180
5181+struct ast_channel *__ast_request_and_dial_uniqueid(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);
5182+
5183 /*! \brief "Requests" a channel for sending a message
5184 * \param type type of channel to request
5185 * \param data data to pass to the channel requester
5186@@ -990,6 +1006,8 @@ struct ast_channel *ast_get_channel_by_e
5187 /*! \brief Get next channel by exten (and optionally context) and lock it */
5188 struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
5189 const char *context);
5190+/*! Get channel by uniqueid (locks channel) */
5191+struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid);
5192
5193 /*! ! \brief Waits for a digit
5194 * \param c channel to wait for a digit on
5195--- a/main/channel.c
5196+++ b/main/channel.c
5197@@ -1017,7 +1017,7 @@ void ast_channel_undefer_dtmf(struct ast
5198 */
5199 static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
5200 const char *name, const int namelen,
5201- const char *context, const char *exten)
5202+ const char *context, const char *exten, const char *uniqueid)
5203 {
5204 const char *msg = prev ? "deadlock" : "initial deadlock";
5205 int retries;
5206@@ -1045,7 +1045,10 @@ static struct ast_channel *channel_find_
5207 * XXX Need a better explanation for this ...
5208 */
5209 }
5210- if (name) { /* want match by name */
5211+ if (uniqueid) {
5212+ if (!strcasecmp(c->uniqueid, uniqueid))
5213+ break;
5214+ } else if (name) { /* want match by name */
5215 if ((!namelen && strcasecmp(c->name, name)) ||
5216 (namelen && strncasecmp(c->name, name, namelen)))
5217 continue; /* name match failed */
5218@@ -1100,39 +1103,44 @@ static struct ast_channel *channel_find_
5219 /*! \brief Browse channels in use */
5220 struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
5221 {
5222- return channel_find_locked(prev, NULL, 0, NULL, NULL);
5223+ return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
5224 }
5225
5226 /*! \brief Get channel by name and lock it */
5227 struct ast_channel *ast_get_channel_by_name_locked(const char *name)
5228 {
5229- return channel_find_locked(NULL, name, 0, NULL, NULL);
5230+ return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
5231 }
5232
5233 /*! \brief Get channel by name prefix and lock it */
5234 struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
5235 {
5236- return channel_find_locked(NULL, name, namelen, NULL, NULL);
5237+ return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
5238 }
5239
5240 /*! \brief Get next channel by name prefix and lock it */
5241 struct ast_channel *ast_walk_channel_by_name_prefix_locked(const struct ast_channel *chan, const char *name,
5242 const int namelen)
5243 {
5244- return channel_find_locked(chan, name, namelen, NULL, NULL);
5245+ return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
5246 }
5247
5248 /*! \brief Get channel by exten (and optionally context) and lock it */
5249 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
5250 {
5251- return channel_find_locked(NULL, NULL, 0, context, exten);
5252+ return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
5253 }
5254
5255 /*! \brief Get next channel by exten (and optionally context) and lock it */
5256 struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
5257 const char *context)
5258 {
5259- return channel_find_locked(chan, NULL, 0, context, exten);
5260+ return channel_find_locked(chan, NULL, 0, context, exten, NULL);
5261+}
5262+
5263+struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
5264+{
5265+ return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
5266 }
5267
5268 /*! \brief Wait, look for hangups and condition arg */
5269@@ -2862,6 +2870,12 @@ char *ast_channel_reason2str(int reason)
5270
5271 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)
5272 {
5273+ return __ast_request_and_dial_uniqueid(type, format, data,
5274+ timeout, outstate, 0, cid_num, cid_name, oh, NULL);
5275+}
5276+
5277+struct ast_channel *__ast_request_and_dial_uniqueid(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)
5278+{
5279 int dummy_outstate;
5280 int cause = 0;
5281 struct ast_channel *chan;
5282@@ -2873,7 +2887,7 @@ struct ast_channel *__ast_request_and_di
5283 else
5284 outstate = &dummy_outstate; /* make outstate always a valid pointer */
5285
5286- chan = ast_request(type, format, data, &cause);
5287+ chan = ast_request_with_uniqueid(type, format, data, &cause, uniqueid);
5288 if (!chan) {
5289 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
5290 /* compute error and return */
5291@@ -2993,8 +3007,12 @@ struct ast_channel *ast_request_and_dial
5292 {
5293 return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
5294 }
5295+struct ast_channel *ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cidnum, const char *cidname, char *uniqueid)
5296+{
5297+ return __ast_request_and_dial_uniqueid(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
5298+}
5299
5300-struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
5301+struct ast_channel *ast_request_with_uniqueid(const char *type, int format, void *data, int *cause, char *uniqueid)
5302 {
5303 struct chanlist *chan;
5304 struct ast_channel *c;
5305@@ -3033,6 +3051,7 @@ struct ast_channel *ast_request(const ch
5306 if (!(c = chan->tech->requester(type, capabilities | videoformat, data, cause)))
5307 return NULL;
5308
5309+ if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
5310 /* no need to generate a Newchannel event here; it is done in the channel_alloc call */
5311 return c;
5312 }
5313@@ -3044,6 +3063,11 @@ struct ast_channel *ast_request(const ch
5314 return NULL;
5315 }
5316
5317+struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
5318+{
5319+ return ast_request_with_uniqueid(type, format, data, cause, NULL);
5320+}
5321+
5322 int ast_call(struct ast_channel *chan, char *addr, int timeout)
5323 {
5324 /* Place an outgoing call, but don't wait any longer than timeout ms before returning.
5325--- a/include/asterisk/pbx.h
5326+++ b/include/asterisk/pbx.h
5327@@ -717,9 +717,17 @@ int ast_async_goto_by_name(const char *c
5328 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);
5329
5330 /*! Synchronously or asynchronously make an outbound call and send it to a
5331+ particular extension (extended version with callinpres and uniqueid) */
5332+int ast_pbx_outgoing_exten_uniqueid(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);
5333+
5334+/*! Synchronously or asynchronously make an outbound call and send it to a
5335 particular application with given extension */
5336 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);
5337
5338+/*! Synchronously or asynchronously make an outbound call and send it to a
5339+ particular application with given extension (extended version with callinpres and uniqueid) */
5340+int ast_pbx_outgoing_app_uniqueid(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);
5341+
5342 /*!
5343 * \brief Evaluate a condition
5344 *
5345--- a/main/pbx.c
5346+++ b/main/pbx.c
5347@@ -4992,7 +4992,7 @@ static int ast_pbx_outgoing_cdr_failed(v
5348 return 0; /* success */
5349 }
5350
5351-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)
5352+int ast_pbx_outgoing_exten_uniqueid(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)
5353 {
5354 struct ast_channel *chan;
5355 struct async_stat *as;
5356@@ -5002,7 +5002,7 @@ int ast_pbx_outgoing_exten(const char *t
5357
5358 if (sync) {
5359 LOAD_OH(oh);
5360- chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
5361+ chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
5362 if (channel) {
5363 *channel = chan;
5364 if (chan)
5365@@ -5094,7 +5094,7 @@ int ast_pbx_outgoing_exten(const char *t
5366 res = -1;
5367 goto outgoing_exten_cleanup;
5368 }
5369- chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
5370+ chan = ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
5371 if (channel) {
5372 *channel = chan;
5373 if (chan)
5374@@ -5134,6 +5134,10 @@ outgoing_exten_cleanup:
5375 return res;
5376 }
5377
5378+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)
5379+{
5380+ return ast_pbx_outgoing_exten_uniqueid(type, format, data, timeout, context, exten, priority, reason, sync, 0, cid_num, cid_name, vars, account, channel, NULL);
5381+}
5382 struct app_tmp {
5383 char app[256];
5384 char data[256];
5385@@ -5158,7 +5162,7 @@ static void *ast_pbx_run_app(void *data)
5386 return NULL;
5387 }
5388
5389-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)
5390+int ast_pbx_outgoing_app_uniqueid(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)
5391 {
5392 struct ast_channel *chan;
5393 struct app_tmp *tmp;
5394@@ -5177,7 +5181,7 @@ int ast_pbx_outgoing_app(const char *typ
5395 goto outgoing_app_cleanup;
5396 }
5397 if (sync) {
5398- chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
5399+ chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
5400 if (chan) {
5401 if (!chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
5402 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */
5403@@ -5259,7 +5263,7 @@ int ast_pbx_outgoing_app(const char *typ
5404 res = -1;
5405 goto outgoing_app_cleanup;
5406 }
5407- chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
5408+ chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
5409 if (!chan) {
5410 free(as);
5411 res = -1;
5412@@ -5299,6 +5303,10 @@ outgoing_app_cleanup:
5413 return res;
5414 }
5415
5416+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)
5417+{
5418+ return ast_pbx_outgoing_app_uniqueid(type, format, data, timeout, app, appdata, reason, sync, 0, cid_num, cid_name, vars, account, locked_channel, NULL);
5419+}
5420 void __ast_context_destroy(struct ast_context *con, const char *registrar)
5421 {
5422 struct ast_context *tmp, *tmpl=NULL;
5423--- a/res/res_monitor.c
5424+++ b/res/res_monitor.c
5425@@ -340,6 +340,11 @@ int ast_monitor_stop(struct ast_channel
5426 result = ast_safe_system(tmp);
5427 if (result == -1)
5428 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
5429+ manager_event(EVENT_FLAG_CALL, "MonitorStopped",
5430+ "Channel: %s\r\n"
5431+ "Uniqueid: %s\r\n"
5432+ "Result: %d\r\n"
5433+ ,chan->name, chan->uniqueid, result);
5434 }
5435
5436 free(chan->monitor->format);
5437@@ -518,18 +523,28 @@ static int start_monitor_action(struct m
5438 const char *fname = astman_get_header(m, "File");
5439 const char *format = astman_get_header(m, "Format");
5440 const char *mix = astman_get_header(m, "Mix");
5441+ const char *uniqueid = astman_get_header(m, "Uniqueid");
5442 const char *target_url = astman_get_header(m, "TargetURL");
5443 const char *target_script = astman_get_header(m, "TargetScript");
5444 char *d;
5445
5446- if (ast_strlen_zero(name)) {
5447- astman_send_error(s, m, "No channel specified");
5448+ if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
5449+ astman_send_error(s, m, "No channel/uniqueid specified");
5450+ return 0;
5451+ }
5452+
5453+ if (!ast_strlen_zero(uniqueid)) {
5454+ c = ast_get_channel_by_uniqueid_locked(uniqueid);
5455+ if (!c) {
5456+ astman_send_error(s, m, "No such uniqueid");
5457 return 0;
5458- }
5459- c = ast_get_channel_by_name_locked(name);
5460- if (!c) {
5461+ }
5462+ } else {
5463+ c = ast_get_channel_by_name_locked(name);
5464+ if (!c) {
5465 astman_send_error(s, m, "No such channel");
5466 return 0;
5467+ }
5468 }
5469
5470 if (ast_strlen_zero(fname)) {
5471@@ -570,16 +585,30 @@ static int stop_monitor_action(struct ma
5472 {
5473 struct ast_channel *c = NULL;
5474 const char *name = astman_get_header(m, "Channel");
5475+ const char *uniqueid = astman_get_header(m, "Uniqueid");
5476 int res;
5477 if (ast_strlen_zero(name)) {
5478 astman_send_error(s, m, "No channel specified");
5479 return 0;
5480 }
5481- c = ast_get_channel_by_name_locked(name);
5482- if (!c) {
5483- astman_send_error(s, m, "No such channel");
5484+ if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
5485+ astman_send_error(s, m, "No channel/uniqueid specified");
5486+ return 0;
5487+ }
5488+ if (!ast_strlen_zero(uniqueid)) {
5489+ c = ast_get_channel_by_uniqueid_locked(uniqueid);
5490+ if (!c) {
5491+ astman_send_error(s, m, "No such uniqueid");
5492 return 0;
5493+ }
5494+ } else {
5495+ c = ast_get_channel_by_name_locked(name);
5496+ if (!c) {
5497+ astman_send_error(s, m, "No such channel");
5498+ return 0;
5499+ }
5500 }
5501+
5502 res = ast_monitor_stop(c, 1);
5503 ast_channel_unlock(c);
5504 if (res) {
5505--- a/apps/app_chanspy.c
5506+++ b/apps/app_chanspy.c
5507@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
5508
5509 static const char *tdesc = "Listen to a channel, and optionally whisper into it";
5510 static const char *app_chan = "ChanSpy";
5511+static const char *app_chan_uniqueid = "ChanSpyChan";
5512 static const char *desc_chan =
5513 " ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
5514 "audio from an Asterisk channel. This includes the audio coming in and\n"
5515@@ -87,6 +88,27 @@ static const char *desc_chan =
5516 " channel.\n"
5517 ;
5518
5519+static const char *desc_uniqueid =
5520+" ChanSpyChan(uniqueid[|options]): This application is used to listen to the\n"
5521+"audio from an Asterisk channel. This includes the audio coming in and\n"
5522+"out of the channel being spied on. The 'uniqueid' parameter has to be specified,\n"
5523+" While spying, the following actions may be performed:\n"
5524+" - Dialing # cycles the volume level.\n"
5525+" Options:\n"
5526+" q - Don't play a beep when beginning to spy on a channel, or speak the\n"
5527+" selected channel name.\n"
5528+" r[(basename)] - Record the session to the monitor spool directory. An\n"
5529+" optional base for the filename may be specified. The\n"
5530+" default is 'chanspy'.\n"
5531+" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
5532+" negative value refers to a quieter setting.\n"
5533+" w - Enable 'whisper' mode, so the spying channel can talk to\n"
5534+" the spied-on channel.\n"
5535+" W - Enable 'private whisper' mode, so the spying channel can\n"
5536+" talk to the spied-on channel but cannot listen to that\n"
5537+" channel.\n"
5538+;
5539+
5540 static const char *app_ext = "ExtenSpy";
5541 static const char *desc_ext =
5542 " ExtenSpy(exten[@context][|options]): This application is used to listen to the\n"
5543@@ -456,7 +478,7 @@ static struct chanspy_ds *setup_chanspy_
5544
5545 static struct chanspy_ds *next_channel(struct ast_channel *chan,
5546 const struct ast_channel *last, const char *spec,
5547- const char *exten, const char *context, struct chanspy_ds *chanspy_ds)
5548+ const char *exten, const char *context, struct chanspy_ds *chanspy_ds, const char *uniqueid)
5549 {
5550 struct ast_channel *this;
5551
5552@@ -465,6 +487,8 @@ redo:
5553 this = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
5554 else if (exten)
5555 this = ast_walk_channel_by_exten_locked(last, exten, context);
5556+ else if (uniqueid)
5557+ this = ast_get_channel_by_uniqueid_locked(uniqueid);
5558 else
5559 this = ast_channel_walk_locked(last);
5560
5561@@ -485,7 +509,7 @@ redo:
5562
5563 static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
5564 int volfactor, const int fd, const char *mygroup, const char *spec,
5565- const char *exten, const char *context)
5566+ const char *exten, const char *context, const char *uniqueid)
5567 {
5568 char nameprefix[AST_NAME_STRLEN];
5569 char peer_name[AST_NAME_STRLEN + 5];
5570@@ -530,11 +554,11 @@ static int common_exec(struct ast_channe
5571 waitms = 100;
5572 num_spyed_upon = 0;
5573
5574- for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds);
5575+ for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds, NULL);
5576 peer_chanspy_ds;
5577 chanspy_ds_free(peer_chanspy_ds), prev = peer,
5578 peer_chanspy_ds = next_chanspy_ds ? next_chanspy_ds :
5579- next_channel(chan, prev, spec, exten, context, &chanspy_ds), next_chanspy_ds = NULL) {
5580+ next_channel(chan, prev, spec, exten, context, &chanspy_ds, NULL), next_chanspy_ds = NULL) {
5581 const char *group;
5582 int igrp = !mygroup;
5583 char *groups[25];
5584@@ -733,7 +757,7 @@ static int chanspy_exec(struct ast_chann
5585 }
5586 }
5587
5588- res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL);
5589+ res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL, NULL);
5590
5591 if (fd)
5592 close(fd);
5593@@ -818,7 +842,7 @@ static int extenspy_exec(struct ast_chan
5594 }
5595 }
5596
5597- res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context);
5598+ res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context, NULL);
5599
5600 if (fd)
5601 close(fd);
5602@@ -831,14 +855,100 @@ static int extenspy_exec(struct ast_chan
5603 return res;
5604 }
5605
5606+static int chanspychan_exec(struct ast_channel *chan, void *data)
5607+{
5608+ struct ast_module_user *u;
5609+ char *options = NULL;
5610+ char *uniqueid = NULL;
5611+ char *argv[2];
5612+ char *mygroup = NULL;
5613+ char *recbase = NULL;
5614+ int fd = 0;
5615+ struct ast_flags flags;
5616+ int oldwf = 0;
5617+ int argc = 0;
5618+ int volfactor = 0;
5619+ int res;
5620+
5621+ data = ast_strdupa(data);
5622+
5623+ u = ast_module_user_add(chan);
5624+
5625+ if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
5626+ uniqueid = argv[0];
5627+ if (argc > 1)
5628+ options = argv[1];
5629+
5630+ if (ast_strlen_zero(uniqueid)) {
5631+ ast_log(LOG_ERROR, "no uniqueid specified.\n");
5632+ ast_module_user_remove(u);
5633+ return -1;
5634+ }
5635+ }
5636+
5637+ if (options) {
5638+ char *opts[OPT_ARG_ARRAY_SIZE];
5639+
5640+ ast_app_parse_options(spy_opts, &flags, opts, options);
5641+ if (ast_test_flag(&flags, OPTION_GROUP))
5642+ mygroup = opts[OPT_ARG_GROUP];
5643+
5644+ if (ast_test_flag(&flags, OPTION_RECORD) &&
5645+ !(recbase = opts[OPT_ARG_RECORD]))
5646+ recbase = "chanspy";
5647+
5648+ if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
5649+ int vol;
5650+
5651+ if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
5652+ ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
5653+ else
5654+ volfactor = vol;
5655+ }
5656+
5657+ if (ast_test_flag(&flags, OPTION_PRIVATE))
5658+ ast_set_flag(&flags, OPTION_WHISPER);
5659+ }
5660+
5661+ oldwf = chan->writeformat;
5662+ if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
5663+ ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
5664+ ast_module_user_remove(u);
5665+ return -1;
5666+ }
5667+
5668+ if (recbase) {
5669+ char filename[512];
5670+
5671+ snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
5672+ if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) {
5673+ ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
5674+ fd = 0;
5675+ }
5676+ }
5677+
5678+ res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, NULL, uniqueid);
5679+
5680+ if (fd)
5681+ close(fd);
5682+
5683+ if (oldwf && ast_set_write_format(chan, oldwf) < 0)
5684+ ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
5685+
5686+ ast_module_user_remove(u);
5687+
5688+ return res;
5689+}
5690+
5691+
5692 static int unload_module(void)
5693 {
5694 int res = 0;
5695
5696 res |= ast_unregister_application(app_chan);
5697+ res |= ast_unregister_application(app_chan_uniqueid);
5698 res |= ast_unregister_application(app_ext);
5699
5700- ast_module_user_hangup_all();
5701
5702 return res;
5703 }
5704@@ -849,6 +959,7 @@ static int load_module(void)
5705
5706 res |= ast_register_application(app_chan, chanspy_exec, tdesc, desc_chan);
5707 res |= ast_register_application(app_ext, extenspy_exec, tdesc, desc_ext);
5708+ res |= ast_register_application(app_chan_uniqueid, chanspychan_exec, tdesc, desc_uniqueid);
5709
5710 return res;
5711 }
5712--- a/main/manager.c
5713+++ b/main/manager.c
5714@@ -87,6 +87,8 @@ struct fast_originate_helper {
5715 char idtext[AST_MAX_EXTENSION];
5716 char account[AST_MAX_ACCOUNT_CODE];
5717 int priority;
5718+ int callingpres;
5719+ char uniqueid[64];
5720 struct ast_variable *vars;
5721 };
5722
5723@@ -1416,11 +1418,20 @@ static int action_hangup(struct mansessi
5724 {
5725 struct ast_channel *c = NULL;
5726 const char *name = astman_get_header(m, "Channel");
5727- if (ast_strlen_zero(name)) {
5728- astman_send_error(s, m, "No channel specified");
5729+ const char *uniqueid = astman_get_header(m, "Uniqueid");
5730+
5731+ if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
5732+ astman_send_error(s, m, "No channel or uniqueid specified");
5733 return 0;
5734 }
5735- c = ast_get_channel_by_name_locked(name);
5736+
5737+ if (!ast_strlen_zero(uniqueid)) {
5738+ c = ast_get_channel_by_uniqueid_locked(uniqueid);
5739+ } else {
5740+ if (!ast_strlen_zero(name))
5741+ c = ast_get_channel_by_name_locked(name);
5742+ }
5743+
5744 if (!c) {
5745 astman_send_error(s, m, "No such channel");
5746 return 0;
5747@@ -1671,12 +1682,18 @@ static int action_redirect(struct manses
5748 const char *exten = astman_get_header(m, "Exten");
5749 const char *context = astman_get_header(m, "Context");
5750 const char *priority = astman_get_header(m, "Priority");
5751+ const char *uniqueid = astman_get_header(m, "Uniqueid");
5752+ const char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
5753+ const char *exten2 = astman_get_header(m, "ExtraExten");
5754+ const char *context2 = astman_get_header(m, "ExtraContext");
5755+ const char *priority2 = astman_get_header(m, "ExtraPriority");
5756 struct ast_channel *chan, *chan2 = NULL;
5757 int pi = 0;
5758+ int pi2 = 0;
5759 int res;
5760
5761- if (ast_strlen_zero(name)) {
5762- astman_send_error(s, m, "Channel not specified");
5763+ if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
5764+ astman_send_error(s, m, "Channel or Uniqueid not specified");
5765 return 0;
5766 }
5767 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
5768@@ -1685,8 +1702,18 @@ static int action_redirect(struct manses
5769 return 0;
5770 }
5771 }
5772+ if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%d", &pi2) != 1)) {
5773+ if ((pi = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) {
5774+ astman_send_error(s, m, "Invalid extra priority\n");
5775+ return 0;
5776+ }
5777+ }
5778 /* XXX watch out, possible deadlock!!! */
5779- chan = ast_get_channel_by_name_locked(name);
5780+ if (!ast_strlen_zero(uniqueid)) {
5781+ chan = ast_get_channel_by_uniqueid_locked(uniqueid);
5782+ } else {
5783+ chan = ast_get_channel_by_name_locked(name);
5784+ }
5785 if (!chan) {
5786 char buf[BUFSIZ];
5787 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
5788@@ -1698,8 +1725,11 @@ static int action_redirect(struct manses
5789 ast_channel_unlock(chan);
5790 return 0;
5791 }
5792- if (!ast_strlen_zero(name2))
5793+ if (!ast_strlen_zero(uniqueid2)) {
5794+ chan2 = ast_get_channel_by_uniqueid_locked(uniqueid2);
5795+ } else if (!ast_strlen_zero(name2)) {
5796 chan2 = ast_get_channel_by_name_locked(name2);
5797+ }
5798 if (chan2 && ast_check_hangup(chan2)) {
5799 astman_send_error(s, m, "Redirect failed, extra channel not up.\n");
5800 ast_channel_unlock(chan);
5801@@ -1708,9 +1738,9 @@ static int action_redirect(struct manses
5802 }
5803 res = ast_async_goto(chan, context, exten, pi);
5804 if (!res) {
5805- if (!ast_strlen_zero(name2)) {
5806+ if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
5807 if (chan2)
5808- res = ast_async_goto(chan2, context, exten, pi);
5809+ res = ast_async_goto(chan2, context2, exten2, pi2);
5810 else
5811 res = -1;
5812 if (!res)
5813@@ -1789,15 +1819,15 @@ static void *fast_originate(void *data)
5814 char requested_channel[AST_CHANNEL_NAME];
5815
5816 if (!ast_strlen_zero(in->app)) {
5817- res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1,
5818+ res = ast_pbx_outgoing_app_uniqueid(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres,
5819 S_OR(in->cid_num, NULL),
5820 S_OR(in->cid_name, NULL),
5821- in->vars, in->account, &chan);
5822+ in->vars, in->account, &chan, in->uniqueid);
5823 } else {
5824- res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
5825+ res = ast_pbx_outgoing_exten_uniqueid(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres,
5826 S_OR(in->cid_num, NULL),
5827 S_OR(in->cid_name, NULL),
5828- in->vars, in->account, &chan);
5829+ in->vars, in->account, &chan, in->uniqueid);
5830 }
5831
5832 if (!chan)
5833@@ -1857,6 +1887,7 @@ static int action_originate(struct manse
5834 const char *appdata = astman_get_header(m, "Data");
5835 const char *async = astman_get_header(m, "Async");
5836 const char *id = astman_get_header(m, "ActionID");
5837+ const char *callingpres = astman_get_header(m, "CallingPres");
5838 struct ast_variable *vars = astman_get_variables(m);
5839 char *tech, *data;
5840 char *l = NULL, *n = NULL;
5841@@ -1866,6 +1897,9 @@ static int action_originate(struct manse
5842 int reason = 0;
5843 char tmp[256];
5844 char tmp2[256];
5845+ char *uniqueid;
5846+ int cpresi = 0;
5847+ char idText[256] = "";
5848
5849 pthread_t th;
5850 pthread_attr_t attr;
5851@@ -1883,6 +1917,10 @@ static int action_originate(struct manse
5852 astman_send_error(s, m, "Invalid timeout\n");
5853 return 0;
5854 }
5855+ if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
5856+ astman_send_error(s, m, "Invalid CallingPres\n");
5857+ return 0;
5858+ }
5859 ast_copy_string(tmp, name, sizeof(tmp));
5860 tech = tmp;
5861 data = strchr(tmp, '/');
5862@@ -1902,6 +1940,7 @@ static int action_originate(struct manse
5863 if (ast_strlen_zero(l))
5864 l = NULL;
5865 }
5866+ uniqueid = ast_alloc_uniqueid();
5867 if (ast_true(async)) {
5868 struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
5869 if (!fast) {
5870@@ -1921,8 +1960,10 @@ static int action_originate(struct manse
5871 ast_copy_string(fast->context, context, sizeof(fast->context));
5872 ast_copy_string(fast->exten, exten, sizeof(fast->exten));
5873 ast_copy_string(fast->account, account, sizeof(fast->account));
5874+ ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
5875 fast->timeout = to;
5876 fast->priority = pi;
5877+ fast->callingpres = cpresi;
5878 pthread_attr_init(&attr);
5879 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
5880 if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
5881@@ -1933,19 +1974,28 @@ static int action_originate(struct manse
5882 pthread_attr_destroy(&attr);
5883 }
5884 } else if (!ast_strlen_zero(app)) {
5885- res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
5886+ res = ast_pbx_outgoing_app_uniqueid(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
5887 } else {
5888 if (exten && context && pi)
5889- res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
5890+ res = ast_pbx_outgoing_exten_uniqueid(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
5891 else {
5892 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
5893 return 0;
5894 }
5895 }
5896- if (!res)
5897- astman_send_ack(s, m, "Originate successfully queued");
5898- else
5899+ if (!res) {
5900+ if (id && !ast_strlen_zero(id)) {
5901+ snprintf(idText,256,"ActionID: %s\r\n",id);
5902+ }
5903+ ast_cli(s->fd, "Response: Success\r\n"
5904+ "%s"
5905+ "Message: Originate successfully queued\r\n"
5906+ "Uniqueid: %s\r\n"
5907+ "\r\n",
5908+ idText, uniqueid);
5909+ } else {
5910 astman_send_error(s, m, "Originate failed");
5911+ }
5912 return 0;
5913 }
5914
5915--- a/include/asterisk/channel.h
5916+++ b/include/asterisk/channel.h
5917@@ -89,6 +89,9 @@
5918
5919 #include "asterisk/abstract_jb.h"
5920
5921+/* Max length of the uniqueid */
5922+#define AST_MAX_UNIQUEID 64
5923+
5924 #include <unistd.h>
5925 #ifdef POLLCOMPAT
5926 #include "asterisk/poll-compat.h"
5927@@ -1039,6 +1042,8 @@ int ast_waitfordigit_full(struct ast_cha
5928 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
5929 int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd);
5930
5931+char *ast_alloc_uniqueid(void);
5932+
5933 /*! \brief Report DTMF on channel 0 */
5934 #define AST_BRIDGE_DTMF_CHANNEL_0 (1 << 0)
5935 /*! \brief Report DTMF on channel 1 */
5936--- a/main/channel.c
5937+++ b/main/channel.c
5938@@ -706,6 +706,15 @@ static const struct ast_channel_tech nul
5939 .description = "Null channel (should not see this)",
5940 };
5941
5942+/*! \brief Create a uniqueid */
5943+char *ast_alloc_uniqueid(void) {
5944+ char *uniqueid;
5945+ uniqueid = malloc(64);
5946+ if (!uniqueid) return NULL;
5947+ snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYSTEM_NAME, ast_mainpid, (long)time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
5948+ return uniqueid;
5949+}
5950+
5951 /*! \brief Create a new channel structure */
5952 struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt, ...)
5953 {
5954--- a/include/asterisk/features.h
5955+++ b/include/asterisk/features.h
5956@@ -47,6 +47,8 @@ struct ast_call_feature {
5957 };
5958
5959
5960+extern int ast_autoanswer_login(struct ast_channel *chan, void *data);
5961+extern int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data);
5962
5963 /*! \brief Park a call and read back parked location
5964 * \param chan the channel to actually be parked
5965--- a/res/res_features.c
5966+++ b/res/res_features.c
5967@@ -11,6 +11,10 @@
5968 * the project provides a web site, mailing lists and IRC
5969 * channels for your use.
5970 *
5971+ * Copyright (C) 2004, Junghanns.NET GmbH
5972+ *
5973+ * Klaus-Peter Junghanns <kpj@junghanns.net>
5974+ *
5975 * This program is free software, distributed under the terms of
5976 * the GNU General Public License Version 2. See the LICENSE file
5977 * at the top of the source tree.
5978@@ -132,6 +136,20 @@ static char *descrip2 = "Park():"
5979 "it already exists. In that case, execution will continue at next\n"
5980 "priority.\n" ;
5981
5982+static char *autoanswerlogin = "AutoanswerLogin";
5983+
5984+static char *synopsis3 = "Log in for autoanswer";
5985+
5986+static char *descrip3 = "AutoanswerLogin([context]|exten):"
5987+"Used to login to the autoanswer application for an extension.\n";
5988+
5989+static char *autoanswer = "Autoanswer";
5990+
5991+static char *synopsis4 = "Autoanswer a call";
5992+
5993+static char *descrip4 = "Autoanswer([context]|exten):"
5994+"Used to autoanswer a call for an extension.\n";
5995+
5996 static struct ast_app *monitor_app = NULL;
5997 static int monitor_ok = 1;
5998
5999@@ -150,6 +168,23 @@ struct parkeduser {
6000 struct parkeduser *next;
6001 };
6002
6003+/* auto answer user */
6004+struct aauser {
6005+ struct ast_channel *chan;
6006+ struct timeval start;
6007+ /* waiting on this extension/context */
6008+ char exten[AST_MAX_EXTENSION];
6009+ char context[AST_MAX_EXTENSION];
6010+ int priority;
6011+ int notquiteyet;
6012+ struct aauser *next;
6013+};
6014+
6015+
6016+static struct aauser *aalot;
6017+AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
6018+static pthread_t autoanswer_thread;
6019+
6020 static struct parkeduser *parkinglot;
6021
6022 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
6023@@ -405,11 +440,13 @@ static int park_call_full(struct ast_cha
6024 "From: %s\r\n"
6025 "Timeout: %ld\r\n"
6026 "CallerID: %s\r\n"
6027- "CallerIDName: %s\r\n",
6028+ "CallerIDName: %s\r\n"
6029+ "Uniqueid: %s\r\n",
6030 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
6031 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
6032 S_OR(pu->chan->cid.cid_num, "<unknown>"),
6033- S_OR(pu->chan->cid.cid_name, "<unknown>")
6034+ S_OR(pu->chan->cid.cid_name, "<unknown>"),
6035+ pu->chan->uniqueid
6036 );
6037
6038 if (peer && adsipark && ast_adsi_available(peer)) {
6039@@ -1656,11 +1693,13 @@ static void post_manager_event(const cha
6040 "Exten: %s\r\n"
6041 "Channel: %s\r\n"
6042 "CallerID: %s\r\n"
6043- "CallerIDName: %s\r\n\r\n",
6044+ "CallerIDName: %s\r\n"
6045+ "Uniqueid: %s\r\n\r\n",
6046 parkingexten,
6047 chan->name,
6048 S_OR(chan->cid.cid_num, "<unknown>"),
6049- S_OR(chan->cid.cid_name, "<unknown>")
6050+ S_OR(chan->cid.cid_name, "<unknown>"),
6051+ chan->uniqueid
6052 );
6053 }
6054
6055@@ -1928,10 +1967,12 @@ static int park_exec(struct ast_channel
6056 "Channel: %s\r\n"
6057 "From: %s\r\n"
6058 "CallerID: %s\r\n"
6059- "CallerIDName: %s\r\n",
6060+ "CallerIDName: %s\r\n"
6061+ "Uniqueid: %s\r\n",
6062 pu->parkingexten, pu->chan->name, chan->name,
6063 S_OR(pu->chan->cid.cid_num, "<unknown>"),
6064- S_OR(pu->chan->cid.cid_name, "<unknown>")
6065+ S_OR(pu->chan->cid.cid_name, "<unknown>"),
6066+ pu->chan->uniqueid
6067 );
6068
6069 free(pu);
6070@@ -2085,15 +2126,10 @@ static struct ast_cli_entry cli_show_fea
6071 handle_showfeatures, NULL,
6072 NULL };
6073
6074-static struct ast_cli_entry cli_features[] = {
6075- { { "feature", "show", NULL },
6076- handle_showfeatures, "Lists configured features",
6077- showfeatures_help, NULL, &cli_show_features_deprecated },
6078+static char showautoanswer_help[] =
6079+"Usage: show autoanswer\n"
6080+" Lists currently logged in autoanswer users.\n";
6081
6082- { { "show", "parkedcalls", NULL },
6083- handle_parkedcalls, "Lists parked calls",
6084- showparked_help },
6085-};
6086
6087 /*! \brief Dump lot status */
6088 static int manager_parking_status( struct mansession *s, const struct message *m)
6089@@ -2117,12 +2153,13 @@ static int manager_parking_status( struc
6090 "Timeout: %ld\r\n"
6091 "CallerID: %s\r\n"
6092 "CallerIDName: %s\r\n"
6093+ "Uniqueid: %s\r\n\r\n"
6094 "%s"
6095 "\r\n",
6096 cur->parkingnum, cur->chan->name, cur->peername,
6097 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
6098 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
6099- S_OR(cur->chan->cid.cid_name, ""),
6100+ S_OR(cur->chan->cid.cid_name, ""), cur->chan->uniqueid,
6101 idText);
6102 }
6103
6104@@ -2197,6 +2234,427 @@ static int manager_park(struct mansessio
6105 return 0;
6106 }
6107
6108+static int handle_autoanswer(int fd, int argc, char *argv[])
6109+{
6110+ struct aauser *cur;
6111+
6112+ ast_cli(fd, "%25s %10s %15s \n", "Channel"
6113+ , "Extension", "Context");
6114+
6115+ ast_mutex_lock(&autoanswer_lock);
6116+
6117+ cur=aalot;
6118+ while(cur) {
6119+ ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
6120+
6121+ cur = cur->next;
6122+ }
6123+
6124+ ast_mutex_unlock(&autoanswer_lock);
6125+
6126+ return RESULT_SUCCESS;
6127+}
6128+
6129+static struct ast_cli_entry cli_features[] = {
6130+ { { "feature", "list", NULL },
6131+ handle_showfeatures, "Lists configured features",
6132+ showfeatures_help, NULL, &cli_show_features_deprecated },
6133+
6134+ { { "show", "parkedcalls", NULL },
6135+ handle_parkedcalls, "Lists parked calls",
6136+ showparked_help },
6137+
6138+ { { "show", "autoanswer", NULL },
6139+ handle_autoanswer, "Lists autoanswer users",
6140+ showautoanswer_help },
6141+};
6142+int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
6143+{
6144+ struct ast_channel *chan;
6145+ struct ast_frame *f;
6146+ /* Make a new, fake channel that we'll use to masquerade in the real one */
6147+ chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name);
6148+ if (chan) {
6149+ /* Let us keep track of the channel name */
6150+ ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name);
6151+ /* Make formats okay */
6152+ chan->readformat = rchan->readformat;
6153+ chan->writeformat = rchan->writeformat;
6154+ ast_channel_masquerade(chan, rchan);
6155+ /* Setup the extensions and such */
6156+ strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
6157+ strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
6158+ chan->priority = rchan->priority;
6159+ /* might be dirty but we want trackable channels */
6160+ ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
6161+ /* Make the masq execute */
6162+ f = ast_read(chan);
6163+ if (f)
6164+ ast_frfree(f);
6165+ ast_autoanswer_login(chan, data);
6166+ } else {
6167+ ast_log(LOG_WARNING, "Unable to create aa channel\n");
6168+ return -1;
6169+ }
6170+ return 0;
6171+}
6172+
6173+static int autoanswer_login_exec(struct ast_channel *chan, void *data)
6174+{
6175+ int res=0;
6176+ struct ast_module_user *u;
6177+
6178+ u = ast_module_user_add(chan);
6179+ if (!data) {
6180+ ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
6181+ return -1;
6182+ }
6183+ res = ast_masq_autoanswer_login(chan, data);
6184+ ast_module_user_remove(u);
6185+ return res;
6186+}
6187+
6188+int ast_autoanswer_login(struct ast_channel *chan, void *data)
6189+{
6190+ /* We put the user in the parking list, then wake up the parking thread to be sure it looks
6191+ after these channels too */
6192+ struct ast_context *con;
6193+ char exten[AST_MAX_EXTENSION];
6194+ struct aauser *pu,*pl = NULL;
6195+ char *s, *stringp, *aacontext, *aaexten = NULL;
6196+
6197+ s = ast_strdupa((void *) data);
6198+ stringp=s;
6199+ aacontext = strsep(&stringp, "|");
6200+ aaexten = strsep(&stringp, "|");
6201+ if (!aaexten) {
6202+ aaexten = aacontext;
6203+ aacontext = NULL;
6204+ }
6205+ if (!aaexten) {
6206+ ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
6207+ return -1;
6208+ } else {
6209+ if (!aacontext) {
6210+ aacontext = "default";
6211+ }
6212+ }
6213+
6214+ ast_mutex_lock(&autoanswer_lock);
6215+ pu = aalot;
6216+ while(pu) {
6217+ if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
6218+ if (pl)
6219+ pl->next = pu->next;
6220+ else
6221+ aalot = pu->next;
6222+ break;
6223+ }
6224+ pl = pu;
6225+ pu = pu->next;
6226+ }
6227+ ast_mutex_unlock(&autoanswer_lock);
6228+ if (pu) {
6229+ ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
6230+ manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
6231+ "Channel: %s\r\n"
6232+ "Uniqueid: %s\r\n"
6233+ "Context: %s\r\n"
6234+ "Exten: %s\r\n"
6235+ ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
6236+ ast_hangup(pu->chan);
6237+ free(pu);
6238+ }
6239+ pu = malloc(sizeof(struct aauser));
6240+ if (pu) {
6241+ memset(pu, 0, sizeof(pu));
6242+ ast_mutex_lock(&autoanswer_lock);
6243+ chan->appl = "Autoanswer";
6244+ chan->data = NULL;
6245+
6246+ pu->chan = chan;
6247+ if (chan->_state != AST_STATE_UP) {
6248+ ast_answer(chan);
6249+ }
6250+
6251+ /* Start music on hold */
6252+ ast_moh_start(pu->chan, NULL, NULL);
6253+ gettimeofday(&pu->start, NULL);
6254+ strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
6255+ strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
6256+ pu->next = aalot;
6257+ aalot = pu;
6258+ con = ast_context_find(aacontext);
6259+ if (!con) {
6260+ con = ast_context_create(NULL,aacontext, registrar);
6261+ if (!con) {
6262+ ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
6263+ }
6264+ }
6265+ if (con) {
6266+ snprintf(exten, sizeof(exten), "%s", aaexten);
6267+ ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
6268+ }
6269+
6270+ ast_mutex_unlock(&autoanswer_lock);
6271+ /* Wake up the (presumably select()ing) thread */
6272+ pthread_kill(autoanswer_thread, SIGURG);
6273+ if (option_verbose > 1)
6274+ ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
6275+ manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
6276+ "Channel: %s\r\n"
6277+ "Uniqueid: %s\r\n"
6278+ "Context: %s\r\n"
6279+ "Exten: %s\r\n"
6280+ ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
6281+
6282+ return 0;
6283+ } else {
6284+ ast_log(LOG_WARNING, "Out of memory\n");
6285+ return -1;
6286+ }
6287+ return 0;
6288+}
6289+
6290+static void autoanswer_reregister_extensions(void)
6291+{
6292+ struct aauser *cur;
6293+ struct ast_context *con;
6294+ char exten[AST_MAX_EXTENSION];
6295+ char args[AST_MAX_EXTENSION];
6296+
6297+ ast_mutex_lock(&autoanswer_lock);
6298+
6299+ cur=aalot;
6300+ while(cur) {
6301+ con = ast_context_find(cur->context);
6302+ if (!con) {
6303+ con = ast_context_create(NULL,cur->context, registrar);
6304+ if (!con) {
6305+ ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", cur->context);
6306+ }
6307+ }
6308+ if (con) {
6309+ snprintf(exten, sizeof(exten), "%s", cur->exten);
6310+ snprintf(args, sizeof(args), "%s|%s", cur->context, cur->exten);
6311+ ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)args), free, registrar);
6312+ }
6313+ cur = cur->next;
6314+ }
6315+
6316+ ast_mutex_unlock(&autoanswer_lock);
6317+}
6318+static void *do_autoanswer_thread(void *ignore)
6319+{
6320+ int ms, tms, max;
6321+ struct ast_context *con;
6322+ char exten[AST_MAX_EXTENSION];
6323+ struct aauser *pu, *pl, *pt = NULL;
6324+ struct timeval tv;
6325+ struct ast_frame *f;
6326+ int x;
6327+ fd_set rfds, efds;
6328+ fd_set nrfds, nefds;
6329+ FD_ZERO(&rfds);
6330+ FD_ZERO(&efds);
6331+ for (;;) {
6332+ ms = -1;
6333+ max = -1;
6334+ ast_mutex_lock(&autoanswer_lock);
6335+ pl = NULL;
6336+ pu = aalot;
6337+ gettimeofday(&tv, NULL);
6338+ FD_ZERO(&nrfds);
6339+ FD_ZERO(&nefds);
6340+ while(pu) {
6341+ tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
6342+ for (x=0;x<AST_MAX_FDS;x++) {
6343+ if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
6344+ if (FD_ISSET(pu->chan->fds[x], &efds))
6345+ ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
6346+ else
6347+ ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
6348+ pu->chan->fdno = x;
6349+ /* See if they need servicing */
6350+ f = ast_read(pu->chan);
6351+ if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
6352+ /* There's a problem, hang them up*/
6353+ if (option_verbose > 1)
6354+ ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
6355+ manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
6356+ "Channel: %s\r\n"
6357+ "Uniqueid: %s\r\n"
6358+ "Context: %s\r\n"
6359+ "Exten: %s\r\n"
6360+ ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
6361+ ast_hangup(pu->chan);
6362+ con = ast_context_find(pu->context);
6363+ if (con) {
6364+ snprintf(exten, sizeof(exten), "%s", pu->exten);
6365+ if (ast_context_remove_extension2(con, exten, 1, registrar))
6366+ ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
6367+ } else {
6368+ ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
6369+ }
6370+ /* And take them out of the parking lot */
6371+ if (pl)
6372+ pl->next = pu->next;
6373+ else
6374+ aalot = pu->next;
6375+ pt = pu;
6376+ pu = pu->next;
6377+ free(pt);
6378+ break;
6379+ } else {
6380+ /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
6381+ ast_frfree(f);
6382+ goto std; /* XXX Ick: jumping into an else statement??? XXX */
6383+ }
6384+ }
6385+ }
6386+ if (x >= AST_MAX_FDS) {
6387+std: for (x=0;x<AST_MAX_FDS;x++) {
6388+ /* Keep this one for next one */
6389+ if (pu->chan->fds[x] > -1) {
6390+ FD_SET(pu->chan->fds[x], &nrfds);
6391+ FD_SET(pu->chan->fds[x], &nefds);
6392+ if (pu->chan->fds[x] > max)
6393+ max = pu->chan->fds[x];
6394+ }
6395+ }
6396+ /* Keep track of our longest wait */
6397+ if ((tms < ms) || (ms < 0))
6398+ ms = tms;
6399+ pl = pu;
6400+ pu = pu->next;
6401+ }
6402+ }
6403+ ast_mutex_unlock(&autoanswer_lock);
6404+ rfds = nrfds;
6405+ efds = nefds;
6406+ tv.tv_sec = ms / 1000;
6407+ tv.tv_usec = (ms % 1000) * 1000;
6408+ /* Wait for something to happen */
6409+ ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
6410+ pthread_testcancel();
6411+ }
6412+ return NULL; /* Never reached */
6413+}
6414+
6415+static int autoanswer_exec(struct ast_channel *chan, void *data)
6416+{
6417+ int res=0;
6418+ struct ast_channel *peer=NULL;
6419+ struct aauser *pu, *pl=NULL;
6420+ struct ast_bridge_config config;
6421+ char *s, *stringp, *aacontext, *aaexten = NULL;
6422+ char datastring[80];
6423+ struct ast_module_user *u;
6424+
6425+
6426+ if (!data) {
6427+ ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
6428+ return -1;
6429+ }
6430+ s = ast_strdupa((void *) data);
6431+ stringp=s;
6432+ aacontext = strsep(&stringp, "|");
6433+ aaexten = strsep(&stringp, "|");
6434+ if (!aaexten) {
6435+ aaexten = aacontext;
6436+ aacontext = NULL;
6437+ }
6438+ if (!aaexten) {
6439+ ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
6440+ return -1;
6441+ } else {
6442+ if (!aacontext) {
6443+ aacontext = "default";
6444+ }
6445+ }
6446+
6447+ u = ast_module_user_add(chan);
6448+ ast_mutex_lock(&autoanswer_lock);
6449+ pu = aalot;
6450+ while(pu) {
6451+ if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
6452+ if (pl)
6453+ pl->next = pu->next;
6454+ else
6455+ aalot = pu->next;
6456+ break;
6457+ }
6458+ pl = pu;
6459+ pu = pu->next;
6460+ }
6461+ ast_mutex_unlock(&autoanswer_lock);
6462+ if (pu) {
6463+ peer = pu->chan;
6464+ free(pu);
6465+ pu = NULL;
6466+ }
6467+ /* JK02: it helps to answer the channel if not already up */
6468+ if (chan->_state != AST_STATE_UP) {
6469+ ast_answer(chan);
6470+ }
6471+
6472+ if (peer) {
6473+ ast_moh_stop(peer);
6474+ /* Play a courtesy beep in the callED channel to prefix the bridge connecting */
6475+ if (!ast_strlen_zero(courtesytone)) {
6476+ if (!ast_streamfile(peer, courtesytone, peer->language)) {
6477+ if (ast_waitstream(peer, "") < 0) {
6478+ ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
6479+ ast_hangup(peer);
6480+ return -1;
6481+ }
6482+ }
6483+ }
6484+
6485+ res = ast_channel_make_compatible(chan, peer);
6486+ if (res < 0) {
6487+ ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
6488+ ast_hangup(peer);
6489+ return -1;
6490+ }
6491+ /* This runs sorta backwards, since we give the incoming channel control, as if it
6492+ were the person called. */
6493+ if (option_verbose > 2)
6494+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered %s\n", peer->name, chan->name);
6495+ manager_event(EVENT_FLAG_CALL, "Autoanswer",
6496+ "Channel: %s\r\n"
6497+ "Uniqueid: %s\r\n"
6498+ "Channel2: %s\r\n"
6499+ "Uniqueid2: %s\r\n"
6500+ "Context: %s\r\n"
6501+ "Exten: %s\r\n"
6502+ ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
6503+
6504+
6505+ memset(&config,0,sizeof(struct ast_bridge_config));
6506+ ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
6507+ ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
6508+ config.timelimit = 0;
6509+ config.play_warning = 0;
6510+ config.warning_freq = 0;
6511+ config.warning_sound=NULL;
6512+ res = ast_bridge_call(chan,peer,&config);
6513+
6514+ if (option_verbose > 2)
6515+ ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
6516+ /* relogin */
6517+ snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
6518+ ast_autoanswer_login(peer, datastring);
6519+ return res;
6520+ } else {
6521+ if (option_verbose > 2)
6522+ ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
6523+ res = -1;
6524+ }
6525+ ast_module_user_remove(u);
6526+ return res;
6527+}
6528+
6529
6530 int ast_pickup_call(struct ast_channel *chan)
6531 {
6532@@ -2460,6 +2918,7 @@ static int load_config(void)
6533
6534 static int reload(void)
6535 {
6536+ autoanswer_reregister_extensions();
6537 return load_config();
6538 }
6539
6540@@ -2483,6 +2942,12 @@ static int load_module(void)
6541 "Park a channel", mandescr_park);
6542 }
6543
6544+ ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
6545+ if (!res)
6546+ res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
6547+ if (!res)
6548+ res |= ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
6549+
6550 res |= ast_devstate_prov_add("Park", metermaidstate);
6551
6552 return res;
6553@@ -2497,6 +2962,8 @@ static int unload_module(void)
6554 ast_manager_unregister("Park");
6555 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
6556 ast_unregister_application(parkcall);
6557+ ast_unregister_application(autoanswer);
6558+ ast_unregister_application(autoanswerlogin);
6559 ast_devstate_prov_del("Park");
6560 return ast_unregister_application(parkedcall);
6561 }
6562--- a/include/asterisk/features.h
6563+++ b/include/asterisk/features.h
6564@@ -72,6 +72,12 @@ int ast_park_call(struct ast_channel *ch
6565 */
6566 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
6567
6568+extern int ast_hold_call(struct ast_channel *chan, struct ast_channel *host);
6569+extern int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *host);
6570+extern int ast_retrieve_call(struct ast_channel *chan, char *uniqueid);
6571+extern int ast_retrieve_call_to_death(char *uniqueid);
6572+extern struct ast_channel *ast_get_holded_call(char *uniqueid);
6573+
6574 /*! \brief Determine system parking extension
6575 * Returns the call parking extension for drivers that provide special
6576 call parking help */
6577--- a/res/res_features.c
6578+++ b/res/res_features.c
6579@@ -66,6 +66,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
6580 #include "asterisk/adsi.h"
6581 #include "asterisk/devicestate.h"
6582 #include "asterisk/monitor.h"
6583+#include "asterisk/indications.h"
6584
6585 #define DEFAULT_PARK_TIME 45000
6586 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
6587@@ -84,6 +85,7 @@ enum {
6588 };
6589
6590 static char *parkedcall = "ParkedCall";
6591+static char *holdedcall = "HoldedCall";
6592
6593 static int parkaddhints = 0; /*!< Add parking hints automatically */
6594 static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
6595@@ -168,6 +170,22 @@ struct parkeduser {
6596 struct parkeduser *next;
6597 };
6598
6599+struct holdeduser {
6600+ struct ast_channel *chan;
6601+ struct timeval start;
6602+ int parkingnum;
6603+ int cref;
6604+ int tei;
6605+ /* Where to go if our parking time expires */
6606+ char context[AST_MAX_EXTENSION];
6607+ char exten[AST_MAX_EXTENSION];
6608+ int priority;
6609+ int parkingtime;
6610+ char uniqueid[AST_MAX_UNIQUEID];
6611+ char uniqueidpeer[AST_MAX_UNIQUEID];
6612+ struct holdeduser *next;
6613+};
6614+
6615 /* auto answer user */
6616 struct aauser {
6617 struct ast_channel *chan;
6618@@ -187,10 +205,16 @@ static pthread_t autoanswer_thread;
6619
6620 static struct parkeduser *parkinglot;
6621
6622+static struct holdeduser *holdlist;
6623+
6624 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
6625
6626+AST_MUTEX_DEFINE_STATIC(holding_lock);
6627+
6628 static pthread_t parking_thread;
6629
6630+static pthread_t holding_thread;
6631+
6632 char *ast_parking_ext(void)
6633 {
6634 return parking_ext;
6635@@ -2052,6 +2076,282 @@ static int park_exec(struct ast_channel
6636 return res;
6637 }
6638
6639+int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
6640+{
6641+ /* We put the user in the parking list, then wake up the parking thread to be sure it looks
6642+ after these channels too */
6643+ struct holdeduser *pu;
6644+ pu = malloc(sizeof(struct holdeduser));
6645+ if (pu) {
6646+ memset(pu, 0, sizeof(pu));
6647+ ast_mutex_lock(&holding_lock);
6648+ chan->appl = "Holded Call";
6649+ chan->data = NULL;
6650+
6651+ pu->chan = chan;
6652+ strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
6653+ strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
6654+ /* Start music on hold */
6655+ ast_moh_start(pu->chan, NULL, NULL);
6656+ gettimeofday(&pu->start, NULL);
6657+ pu->next = holdlist;
6658+ holdlist = pu;
6659+ ast_mutex_unlock(&holding_lock);
6660+ /* Wake up the (presumably select()ing) thread */
6661+ pthread_kill(holding_thread, SIGURG);
6662+
6663+ manager_event(EVENT_FLAG_CALL, "HoldedCall",
6664+ "Channel1: %s\r\n"
6665+ "Channel2: %s\r\n"
6666+ "Uniqueid1: %s\r\n"
6667+ "Uniqueid2: %s\r\n"
6668+ ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
6669+
6670+ } else {
6671+ ast_log(LOG_WARNING, "Out of memory\n");
6672+ return -1;
6673+ }
6674+ return 0;
6675+}
6676+
6677+int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
6678+{
6679+ struct ast_channel *chan;
6680+ struct ast_frame *f;
6681+ /* Make a new, fake channel that we'll use to masquerade in the real one */
6682+ chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name);
6683+ if (chan) {
6684+ /* Let us keep track of the channel name */
6685+ ast_string_field_build(chan, name, "Onhold/%s",rchan->name);
6686+ /* Make formats okay */
6687+ chan->readformat = rchan->readformat;
6688+ chan->writeformat = rchan->writeformat;
6689+ ast_channel_masquerade(chan, rchan);
6690+ /* Setup the extensions and such */
6691+ strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
6692+ strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
6693+ chan->priority = rchan->priority;
6694+ /* this might be dirty, but we need to preserve the uniqueid */
6695+ ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
6696+ /* Make the masq execute */
6697+ f = ast_read(chan);
6698+ if (f)
6699+ ast_frfree(f);
6700+ ast_hold_call(chan, peer);
6701+ return -1;
6702+ } else {
6703+ ast_log(LOG_WARNING, "Unable to create holded channel\n");
6704+ return -1;
6705+ }
6706+ return 0;
6707+}
6708+
6709+int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
6710+{
6711+ int res=-1, dres=-1;
6712+ struct ast_channel *peer=NULL;
6713+ struct ast_bridge_config config;
6714+
6715+ peer = ast_get_holded_call(uniqueid);
6716+
6717+ /* JK02: it helps to answer the channel if not already up */
6718+ if (chan->_state != AST_STATE_UP) {
6719+ ast_answer(chan);
6720+ }
6721+
6722+ if (peer) {
6723+ ast_mutex_unlock(&peer->lock);
6724+ ast_moh_stop(peer);
6725+ res = ast_channel_make_compatible(chan, peer);
6726+ if (res < 0) {
6727+ ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
6728+ ast_hangup(peer);
6729+ return -1;
6730+ }
6731+ /* This runs sorta backwards, since we give the incoming channel control, as if it
6732+ were the person called. */
6733+ if (option_verbose > 2)
6734+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
6735+
6736+ memset(&config,0,sizeof(struct ast_bridge_config));
6737+ ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
6738+ ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
6739+ config.timelimit = 0;
6740+ config.play_warning = 0;
6741+ config.warning_freq = 0;
6742+ config.warning_sound=NULL;
6743+ res = ast_bridge_call(chan,peer,&config);
6744+
6745+ /* Simulate the PBX hanging up */
6746+ if (res != AST_PBX_NO_HANGUP_PEER)
6747+ ast_hangup(peer);
6748+ return res;
6749+ } else {
6750+ /* XXX Play a message XXX */
6751+ dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
6752+ if (!dres)
6753+ dres = ast_waitstream(chan, "");
6754+ else {
6755+ ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
6756+ dres = 0;
6757+ }
6758+ }
6759+ return res;
6760+}
6761+
6762+int ast_retrieve_call_to_death(char *uniqueid)
6763+{
6764+ int res=-1;
6765+ struct ast_channel *peer=NULL;
6766+
6767+ peer = ast_get_holded_call(uniqueid);
6768+
6769+ if (peer) {
6770+ res=0;
6771+ if (option_verbose > 2)
6772+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
6773+ ast_mutex_unlock(&peer->lock);
6774+ ast_hangup(peer);
6775+ } else {
6776+ ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
6777+ }
6778+ return res;
6779+}
6780+
6781+struct ast_channel *ast_get_holded_call(char *uniqueid)
6782+{
6783+ int res=-1;
6784+ struct ast_channel *peer=NULL;
6785+ struct holdeduser *pu, *pl=NULL;
6786+
6787+ ast_mutex_lock(&holding_lock);
6788+ pu = holdlist;
6789+ while(pu) {
6790+ if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
6791+ if (pl)
6792+ pl->next = pu->next;
6793+ else
6794+ holdlist = pu->next;
6795+ break;
6796+ }
6797+ pl = pu;
6798+ pu = pu->next;
6799+ }
6800+ ast_mutex_unlock(&holding_lock);
6801+ if (pu) {
6802+ peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
6803+ free(pu);
6804+ if (peer) {
6805+ res=0;
6806+ if (option_verbose > 2)
6807+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
6808+ ast_moh_stop(peer);
6809+ return peer;
6810+ } else {
6811+ if (option_verbose > 2)
6812+ ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
6813+ return NULL;
6814+ }
6815+ } else {
6816+ ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
6817+ }
6818+ return NULL;
6819+}
6820+
6821+/* this is our autmagically service thread that keeps channels onhold happy */
6822+static void *do_holding_thread(void *ignore)
6823+{
6824+ int ms, tms, max;
6825+ struct holdeduser *pu, *pl, *pt = NULL;
6826+ struct timeval tv;
6827+ struct ast_frame *f;
6828+ int x;
6829+ fd_set rfds, efds;
6830+ fd_set nrfds, nefds;
6831+ FD_ZERO(&rfds);
6832+ FD_ZERO(&efds);
6833+ for (;;) {
6834+ ms = -1;
6835+ max = -1;
6836+ ast_mutex_lock(&holding_lock);
6837+ pl = NULL;
6838+ pu = holdlist;
6839+ gettimeofday(&tv, NULL);
6840+ FD_ZERO(&nrfds);
6841+ FD_ZERO(&nefds);
6842+ while(pu) {
6843+ tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
6844+ for (x=0;x<AST_MAX_FDS;x++) {
6845+ if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
6846+ if (FD_ISSET(pu->chan->fds[x], &efds))
6847+ ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
6848+ else
6849+ ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
6850+ pu->chan->fdno = x;
6851+ /* See if they need servicing */
6852+ f = ast_read(pu->chan);
6853+ if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
6854+ /* There's a problem, hang them up*/
6855+ if (option_verbose > 1)
6856+ ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
6857+ ast_hangup(pu->chan);
6858+ /* find the corresponding channel and hang them up too! */
6859+ /* but only if it is not bridged yet! */
6860+ /* And take them out of the parking lot */
6861+ if (pl)
6862+ pl->next = pu->next;
6863+ else
6864+ holdlist = pu->next;
6865+ pt = pu;
6866+ pu = pu->next;
6867+ free(pt);
6868+ break;
6869+ } else {
6870+ /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
6871+ ast_frfree(f);
6872+ goto std; /* XXX Ick: jumping into an else statement??? XXX */
6873+ }
6874+ }
6875+ }
6876+ if (x >= AST_MAX_FDS) {
6877+std: for (x=0;x<AST_MAX_FDS;x++) {
6878+ /* Keep this one for next one */
6879+ if (pu->chan->fds[x] > -1) {
6880+ FD_SET(pu->chan->fds[x], &nrfds);
6881+ FD_SET(pu->chan->fds[x], &nefds);
6882+ if (pu->chan->fds[x] > max)
6883+ max = pu->chan->fds[x];
6884+ }
6885+ }
6886+ /* Keep track of our longest wait */
6887+ if ((tms < ms) || (ms < 0))
6888+ ms = tms;
6889+ pl = pu;
6890+ pu = pu->next;
6891+ }
6892+ }
6893+ ast_mutex_unlock(&holding_lock);
6894+ rfds = nrfds;
6895+ efds = nefds;
6896+ tv.tv_sec = ms / 1000;
6897+ tv.tv_usec = (ms % 1000) * 1000;
6898+ /* Wait for something to happen */
6899+ ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
6900+ pthread_testcancel();
6901+ }
6902+ return NULL; /* Never reached */
6903+}
6904+
6905+static int retrieve_call_exec(struct ast_channel *chan, void *data) {
6906+ int res=0;
6907+ struct ast_module_user *u;
6908+ char *uniqueid = (char *)data;
6909+ u = ast_module_user_add(chan);
6910+ res = ast_retrieve_call(chan, uniqueid);
6911+ ast_module_user_remove(u);
6912+ return res;
6913+}
6914+
6915 static int handle_showfeatures(int fd, int argc, char *argv[])
6916 {
6917 int i;
6918@@ -2933,6 +3233,7 @@ static int load_module(void)
6919 return res;
6920 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
6921 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
6922+ ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
6923 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
6924 if (!res)
6925 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
6926@@ -2942,6 +3243,7 @@ static int load_module(void)
6927 "Park a channel", mandescr_park);
6928 }
6929
6930+ res |= ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
6931 ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
6932 if (!res)
6933 res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
6934@@ -2964,6 +3266,7 @@ static int unload_module(void)
6935 ast_unregister_application(parkcall);
6936 ast_unregister_application(autoanswer);
6937 ast_unregister_application(autoanswerlogin);
6938+ ast_unregister_application(holdedcall);
6939 ast_devstate_prov_del("Park");
6940 return ast_unregister_application(parkedcall);
6941 }
6942--- a/channels/chan_zap.c
6943+++ b/channels/chan_zap.c
6944@@ -77,6 +77,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
6945 #ifdef HAVE_PRI
6946 #include <bristuffed/libpri.h>
6947 #endif
6948+#ifdef HAVE_GSMAT
6949+#include <libgsmat.h>
6950+#endif
6951
6952 #include "asterisk/lock.h"
6953 #include "asterisk/channel.h"
6954@@ -185,6 +188,7 @@ static const char config[] = "zapata.con
6955 #define SIG_FXOGS ZT_SIG_FXOGS
6956 #define SIG_FXOKS ZT_SIG_FXOKS
6957 #define SIG_PRI ZT_SIG_CLEAR
6958+#define SIG_GSM (0x100000 | ZT_SIG_CLEAR)
6959 #define SIG_SF ZT_SIG_SF
6960 #define SIG_SFWINK (0x0100000 | ZT_SIG_SF)
6961 #define SIG_SF_FEATD (0x0200000 | ZT_SIG_SF)
6962@@ -234,6 +238,8 @@ static int matchdigittimeout = 3000;
6963 /*! \brief Protect the interface list (of zt_pvt's) */
6964 AST_MUTEX_DEFINE_STATIC(iflock);
6965
6966+static char gsm_modem_pin[20];
6967+static char gsm_modem_exten[AST_MAX_EXTENSION];
6968
6969 static int ifcount = 0;
6970
6971@@ -251,6 +257,7 @@ static enum ast_bridge_result zt_bridge(
6972
6973 static int zt_sendtext(struct ast_channel *c, const char *text);
6974
6975+static int zt_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu);
6976
6977 /*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
6978 static inline int zt_get_event(int fd)
6979@@ -364,6 +371,19 @@ struct zt_pri {
6980 int debugfd;
6981 };
6982
6983+#ifdef HAVE_GSMAT
6984+struct zt_gsm {
6985+ pthread_t master;
6986+ ast_mutex_t lock; /* Mutex */
6987+ int fd;
6988+ int span;
6989+ struct gsm_modul *modul;
6990+ char pin[256];
6991+ int available;
6992+ char exten[AST_MAX_EXTENSION]; /* Where to idle extra calls */
6993+ struct zt_pvt *pvt;
6994+};
6995+#endif
6996
6997 static struct zt_pri pris[NUM_SPANS];
6998
6999@@ -392,6 +412,7 @@ struct zt_pri;
7000 #define POLARITY_REV 1
7001
7002
7003+
7004 static struct zt_distRings drings;
7005
7006 struct distRingData {
7007@@ -604,6 +625,9 @@ static struct zt_pvt {
7008 int prioffset;
7009 int logicalspan;
7010 #endif
7011+#ifdef HAVE_GSMAT
7012+ struct zt_gsm gsm;
7013+#endif
7014 int polarity;
7015 int dsp_features;
7016 char begindigit;
7017@@ -710,7 +734,7 @@ static struct zt_chan_conf zt_chan_conf_
7018 static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause);
7019 static int zt_digit_begin(struct ast_channel *ast, char digit);
7020 static int zt_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
7021-static int zt_sendtext(struct ast_channel *c, const char *text);
7022+static int zt_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu);
7023 static int zt_call(struct ast_channel *ast, char *rdest, int timeout);
7024 static int zt_hangup(struct ast_channel *ast);
7025 static int zt_answer(struct ast_channel *ast);
7026@@ -732,6 +756,9 @@ static const struct ast_channel_tech zap
7027 .send_digit_begin = zt_digit_begin,
7028 .send_digit_end = zt_digit_end,
7029 .send_text = zt_sendtext,
7030+#if 0 /* we (Debian) disable that addition because of ABI breakage */
7031+ .send_message = zt_sendmessage,
7032+#endif
7033 .call = zt_call,
7034 .hangup = zt_hangup,
7035 .answer = zt_answer,
7036@@ -1262,6 +1289,8 @@ static char *zap_sig2str(int sig)
7037 return "GR-303 with FXOKS";
7038 case SIG_GR303FXSKS:
7039 return "GR-303 with FXSKS";
7040+ case SIG_GSM:
7041+ return "GSM";
7042 case 0:
7043 return "Pseudo";
7044 default:
7045@@ -1683,7 +1712,7 @@ static inline int zt_confmute(struct zt_
7046 {
7047 int x, y, res;
7048 x = muted;
7049- if (p->sig == SIG_PRI) {
7050+ if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
7051 y = 1;
7052 res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
7053 if (res)
7054@@ -2098,6 +2127,25 @@ static int zt_call(struct ast_channel *a
7055 p->dialdest[0] = '\0';
7056 disable_dtmf_detect(p);
7057 break;
7058+ case SIG_GSM:
7059+#ifdef HAVE_GSMAT
7060+ if (p->gsm.modul) {
7061+ c = strchr(dest, '/');
7062+ if (c)
7063+ c++;
7064+ else
7065+ c = dest;
7066+ ast_mutex_lock(&p->gsm.lock);
7067+ if (gsm_dial(p->gsm.modul, p->use_callingpres ? ast->cid.cid_pres : 0, c)) {
7068+ ast_log(LOG_WARNING, "dialing failed on channel %d\n", p->channel);
7069+ ast_mutex_unlock(&p->gsm.lock);
7070+ ast_mutex_unlock(&p->lock);
7071+ return -1;
7072+ }
7073+ ast_mutex_unlock(&p->gsm.lock);
7074+ }
7075+#endif
7076+ break;
7077 default:
7078 ast_log(LOG_DEBUG, "not yet implemented\n");
7079 ast_mutex_unlock(&p->lock);
7080@@ -2737,7 +2785,13 @@ static int zt_hangup(struct ast_channel
7081 }
7082 }
7083 #endif
7084- if (p->sig && (p->sig != SIG_PRI))
7085+#ifdef HAVE_GSMAT
7086+ if (p->gsm.modul) {
7087+ if (!p->alreadyhungup)
7088+ gsm_hangup(p->gsm.modul);
7089+ }
7090+#endif
7091+ if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_GSM))
7092 res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
7093 if (res < 0) {
7094 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
7095@@ -2914,6 +2968,13 @@ static int zt_answer(struct ast_channel
7096 zt_train_ec(p);
7097 break;
7098 #endif
7099+#ifdef HAVE_GSMAT
7100+ case SIG_GSM:
7101+ if (p->gsm.modul) {
7102+ gsm_answer(p->gsm.modul);
7103+ }
7104+ break;
7105+#endif
7106 case 0:
7107 ast_mutex_unlock(&p->lock);
7108 return 0;
7109@@ -7302,6 +7363,10 @@ static int pri_create_spanmap(int span,
7110
7111 #endif
7112
7113+#ifdef HAVE_GSMAT
7114+static void *gsm_dchannel(void *vgsm);
7115+#endif
7116+
7117 static struct zt_pvt *mkintf(int channel, const struct zt_chan_conf *conf, struct zt_pri *pri, int reloading)
7118 {
7119 /* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
7120@@ -7530,6 +7595,37 @@ static struct zt_pvt *mkintf(int channel
7121 tmp->prioffset = 0;
7122 }
7123 #endif
7124+#ifdef HAVE_GSMAT
7125+ if (conf->chan.sig == SIG_GSM) {
7126+ struct zt_bufferinfo bi;
7127+ ast_mutex_init(&tmp->gsm.lock);
7128+ strncpy(tmp->gsm.pin, gsm_modem_pin, sizeof(tmp->gsm.pin) - 1);
7129+ strncpy(tmp->gsm.exten, gsm_modem_exten, sizeof(tmp->gsm.exten) - 1);
7130+ tmp->gsm.available = 0;
7131+ snprintf(fn, sizeof(fn), "%d", channel + 1);
7132+ /* Open non-blocking */
7133+ tmp->gsm.fd = zt_open(fn);
7134+ bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
7135+ bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
7136+ bi.numbufs = 16;
7137+ bi.bufsize = 1024;
7138+ if (ioctl(tmp->gsm.fd, ZT_SET_BUFINFO, &bi)) {
7139+ ast_log(LOG_ERROR, "Unable to set buffer info on channel '%s': %s\n", fn, strerror(errno));
7140+ return NULL;
7141+ }
7142+ tmp->gsm.pvt = tmp;
7143+ tmp->gsm.span = tmp->span;
7144+ tmp->gsm.modul = gsm_new(tmp->gsm.fd, 0, tmp->gsm.pin, tmp->span, tmp->channel);
7145+ if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, tmp->channel)) {
7146+ ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d: %s\n", tmp->channel, strerror(errno));
7147+ destroy_zt_pvt(&tmp);
7148+ return NULL;
7149+ }
7150+ if (ast_pthread_create(&tmp->gsm.master, NULL, gsm_dchannel, &tmp->gsm)) {
7151+ zt_close(tmp->gsm.fd);
7152+ }
7153+ }
7154+#endif
7155 } else {
7156 conf->chan.sig = tmp->sig;
7157 conf->chan.radio = tmp->radio;
7158@@ -7819,6 +7915,12 @@ static inline int available(struct zt_pv
7159 return 1;
7160 }
7161 #endif
7162+#ifdef HAVE_GSMAT
7163+ if (p->gsm.modul) {
7164+ return gsm_available(p->gsm.modul);
7165+ }
7166+
7167+#endif
7168 if (!(p->radio || (p->oprmode < 0)))
7169 {
7170 if (!p->sig || (p->sig == SIG_FXSLS))
7171@@ -8176,6 +8278,235 @@ next:
7172 return tmp;
7173 }
7174
7175+#ifdef HAVE_GSMAT
7176+static int zt_reset_span(int span, int sleep) {
7177+ int ctl;
7178+ int res;
7179+
7180+ ctl = open("/dev/zap/ctl", O_RDWR);
7181+ if (ctl < 0) {
7182+ ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
7183+ return -1;
7184+ }
7185+ ast_verbose(VERBOSE_PREFIX_2 "Shutting down span %d. Please wait...\n", span);
7186+ res = ioctl(ctl, ZT_SHUTDOWN, &span);
7187+ if (res) {
7188+ ast_log(LOG_WARNING, "error shutting down span %d\n", span);
7189+ return -1;
7190+ }
7191+ usleep(sleep * 1000);
7192+ ast_verbose(VERBOSE_PREFIX_2 "Starting up span %d. Please wait...\n", span);
7193+ res = ioctl(ctl, ZT_STARTUP, &span);
7194+ if (res) {
7195+ ast_log(LOG_WARNING, "error starting up span %d\n", span);
7196+ return -1;
7197+ }
7198+ ast_verbose(VERBOSE_PREFIX_2 "Reset of span %d completed.\n", span);
7199+ return 0;
7200+}
7201+
7202+
7203+static void handle_gsm_event(struct zt_gsm *gsm, gsm_event *e)
7204+{
7205+ struct ast_channel *c = NULL;
7206+ int law = ZT_LAW_ALAW;
7207+ int res = 0;
7208+
7209+ switch(e->e) {
7210+ case GSM_EVENT_DCHAN_UP:
7211+ if (option_verbose > 2)
7212+ ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d registered to network!\n", gsm->span);
7213+ gsm->available = 1;
7214+ break;
7215+ case GSM_EVENT_DCHAN_DOWN:
7216+ if (option_verbose > 2)
7217+ ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d unregistered from network!\n", gsm->span);
7218+ gsm->available = 0;
7219+/* ast_mutex_lock(&gsm->pvt->lock);
7220+ gsm->pvt->alreadyhungup = 1;
7221+ if (gsm->pvt->owner) {
7222+ gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7223+ }
7224+ ast_mutex_unlock(&gsm->pvt->lock); */
7225+ break;
7226+ case GSM_EVENT_RING:
7227+ ast_mutex_lock(&gsm->pvt->lock);
7228+ if (!ast_strlen_zero(e->ring.callingnum)) {
7229+ strncpy(gsm->pvt->cid_num, e->ring.callingnum, sizeof(gsm->pvt->cid_num) - 1);
7230+ } else {
7231+ strncpy(gsm->pvt->cid_name, "CID withheld", sizeof(gsm->pvt->cid_name));
7232+ }
7233+ if (!ast_strlen_zero(gsm->exten)) {
7234+ strncpy(gsm->pvt->exten, gsm->exten, sizeof(gsm->pvt->exten) - 1);
7235+ } else {
7236+ gsm->pvt->exten[0] = 's';
7237+ gsm->pvt->exten[1] = '\0';
7238+ }
7239+ c = zt_new(gsm->pvt, AST_STATE_RING, 1, SUB_REAL, ZT_LAW_ALAW, AST_TRANS_CAP_SPEECH);
7240+ if (c) {
7241+ if (option_verbose > 2)
7242+ ast_verbose(VERBOSE_PREFIX_3 "Ring on channel %d (from %s to %s)\n", e->ring.channel, e->ring.callingnum, gsm->exten);
7243+ gsm->pvt->owner = c;
7244+ if (ioctl(gsm->pvt->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
7245+ ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", gsm->pvt->channel, law);
7246+ res = zt_setlaw(gsm->pvt->subs[SUB_REAL].zfd, law);
7247+ res = set_actual_gain(gsm->pvt->subs[SUB_REAL].zfd, 0, gsm->pvt->rxgain, gsm->pvt->txgain, law);
7248+ if (res < 0) {
7249+ ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", gsm->pvt->channel);
7250+// } else {
7251+// 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);
7252+ }
7253+ }
7254+ ast_mutex_unlock(&gsm->pvt->lock);
7255+ break;
7256+ case GSM_EVENT_HANGUP:
7257+ ast_verbose(VERBOSE_PREFIX_3 "Got hang up on channel %d\n", e->hangup.channel);
7258+ ast_mutex_lock(&gsm->pvt->lock);
7259+ gsm->pvt->alreadyhungup = 1;
7260+ if (gsm->pvt->owner) {
7261+ gsm->pvt->owner->hangupcause = e->hangup.cause;
7262+ gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7263+ }
7264+ ast_mutex_unlock(&gsm->pvt->lock);
7265+ break;
7266+ case GSM_EVENT_ERROR:
7267+ ast_log(LOG_WARNING, "Got error on channel\n");
7268+ ast_mutex_lock(&gsm->pvt->lock);
7269+ gsm->pvt->alreadyhungup = 1;
7270+ if (gsm->pvt->owner) {
7271+ gsm->pvt->owner->hangupcause = e->error.cause;
7272+ gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7273+ }
7274+ ast_mutex_unlock(&gsm->pvt->lock);
7275+ if (e->error.hard) {
7276+// gsm_poweroff(gsm->modul);
7277+ zt_reset_span(gsm->span, 8000);
7278+// gsm_restart(gsm->modul, 10000);
7279+ } else {
7280+// gsm_poweroff(gsm->modul);
7281+ zt_reset_span(gsm->span, 8000);
7282+// gsm_restart(gsm->modul, 10000);
7283+ }
7284+ break;
7285+ case GSM_EVENT_ALERTING:
7286+ ast_mutex_lock(&gsm->pvt->lock);
7287+ gsm->pvt->subs[SUB_REAL].needringing =1;
7288+ ast_mutex_unlock(&gsm->pvt->lock);
7289+ break;
7290+ case GSM_EVENT_ANSWER:
7291+ ast_mutex_lock(&gsm->pvt->lock);
7292+ gsm->pvt->dialing = 0;
7293+ gsm->pvt->subs[SUB_REAL].needanswer =1;
7294+ gsm->pvt->ignoredtmf = 0;
7295+ ast_mutex_unlock(&gsm->pvt->lock);
7296+ break;
7297+ case GSM_EVENT_PIN_REQUIRED:
7298+ gsm_send_pin(gsm->modul, gsm->pin);
7299+ break;
7300+ case GSM_EVENT_SM_RECEIVED:
7301+ ast_verbose(VERBOSE_PREFIX_3 "SMS from %s received on span %d. (Text: %s) (PDU: %s)\n", e->sm_received.sender, gsm->span, e->sm_received.text, e->sm_received.pdu);
7302+ manager_event(EVENT_FLAG_CALL, "Message received",
7303+ "Span: %d\r\n"
7304+ "Sender: %s\r\n"
7305+ "SMSC: %s\r\n"
7306+ "Length: %d\r\n"
7307+ "Text: %s\r\n"
7308+ "PDU: %s\r\n",
7309+ gsm->span,
7310+ e->sm_received.sender,
7311+ e->sm_received.smsc,
7312+ e->sm_received.len,
7313+ e->sm_received.text,
7314+ e->sm_received.pdu);
7315+ break;
7316+ default:
7317+ ast_log(LOG_WARNING,"!! Unknown GSM event %d !!\n", e->e);
7318+ }
7319+}
7320+
7321+static void *gsm_dchannel(void *vgsm)
7322+{
7323+ struct zt_gsm *gsm = vgsm;
7324+ gsm_event *e;
7325+ struct timeval tv = {0,0}, *next;
7326+ fd_set rfds, efds;
7327+ int res,x;
7328+
7329+ if (!gsm) return NULL;
7330+
7331+ if (!gsm->modul) {
7332+ fprintf(stderr, "No gsm_mod\n");
7333+ return NULL;
7334+ }
7335+ gsm_set_debug(gsm->modul, GSM_DEBUG_NONE);
7336+ for (;;) {
7337+
7338+ /* Run the D-Channel */
7339+ FD_ZERO(&rfds);
7340+ FD_ZERO(&efds);
7341+ FD_SET(gsm->fd, &rfds);
7342+ FD_SET(gsm->fd, &efds);
7343+
7344+ if ((next = gsm_schedule_next(gsm->modul))) {
7345+ gettimeofday(&tv, NULL);
7346+ tv.tv_sec = next->tv_sec - tv.tv_sec;
7347+ tv.tv_usec = next->tv_usec - tv.tv_usec;
7348+ if (tv.tv_usec < 0) {
7349+ tv.tv_usec += 1000000;
7350+ tv.tv_sec -= 1;
7351+ }
7352+ if (tv.tv_sec < 0) {
7353+ tv.tv_sec = 0;
7354+ tv.tv_usec = 0;
7355+ }
7356+ }
7357+ res = select(gsm->fd + 1, &rfds, NULL, &efds, next ? &tv : NULL);
7358+ e = NULL;
7359+
7360+ ast_mutex_lock(&gsm->lock);
7361+ if (!res) {
7362+ e = gsm_schedule_run(gsm->modul);
7363+ } else if (res > 0) {
7364+ e = gsm_check_event(gsm->modul, 1);
7365+ } else if (errno == ELAST) {
7366+ res = ioctl(gsm->fd, ZT_GETEVENT, &x);
7367+ printf("Got Zaptel event: %d\n", x);
7368+ } else if (errno != EINTR)
7369+ fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
7370+
7371+ if (!e) {
7372+ e = gsm_check_event(gsm->modul, 0);
7373+ }
7374+
7375+ if (e) {
7376+ handle_gsm_event(gsm, e);
7377+ }
7378+ ast_mutex_unlock(&gsm->lock);
7379+
7380+ res = ioctl(gsm->fd, ZT_GETEVENT, &x);
7381+
7382+ if (!res && x) {
7383+ switch (x) {
7384+ case ZT_EVENT_NOALARM:
7385+ ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", gsm->span);
7386+ usleep(1000);
7387+ gsm_restart(gsm->modul, 10000);
7388+ break;
7389+ case ZT_EVENT_ALARM:
7390+ ast_log(LOG_NOTICE, "Alarm detected on span %d\n", gsm->span);
7391+ break;
7392+ default:
7393+ fprintf(stderr, "Got event on GSM interface: %d\n", x);
7394+ }
7395+ }
7396+
7397+
7398+ }
7399+ return NULL;
7400+}
7401+
7402+#endif
7403+
7404 #ifdef HAVE_PRI
7405 static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
7406 {
7407@@ -8450,6 +8781,18 @@ static void zt_pri_error(char *s, int sp
7408 ast_log(LOG_WARNING, "%d %s", span, s);
7409 }
7410
7411+#ifdef HAVE_GSMAT
7412+static void zt_gsm_message(char *s, int channel)
7413+{
7414+ ast_verbose("GSM %d: %s", channel, s);
7415+}
7416+
7417+static void zt_gsm_error(char *s, int channel)
7418+{
7419+ ast_log(LOG_WARNING, "GSM %d: %s", channel, s);
7420+}
7421+#endif
7422+
7423 static int pri_check_restart(struct zt_pri *pri)
7424 {
7425 if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
7426@@ -10868,6 +11211,243 @@ static int app_zapInband(struct ast_chan
7427
7428 #endif /* HAVE_PRI */
7429
7430+#ifdef HAVE_GSMAT
7431+static int handle_zap_reset_span(int fd, int argc, char *argv[])
7432+{
7433+ int span;
7434+ int sleep = 5000;
7435+ if (argc < 4)
7436+ return RESULT_SHOWUSAGE;
7437+ span = atoi(argv[3]);
7438+ if ((span < 1) || (span > NUM_SPANS)) {
7439+ ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
7440+ return RESULT_SUCCESS;
7441+ }
7442+ if (zt_reset_span(span, sleep)) {
7443+ return RESULT_FAILURE;
7444+ }
7445+ return RESULT_SUCCESS;
7446+}
7447+
7448+static int handle_gsm_debug_helper(int fd, int channel, int debug)
7449+{
7450+/* gsm debug channel <channel> */
7451+ struct zt_pvt *pvt = NULL;
7452+ if (channel < 1) {
7453+ ast_cli(fd, "Invalid channel %d. Should be a number.\n", channel);
7454+ return RESULT_SUCCESS;
7455+ }
7456+ pvt = iflist;
7457+ while (pvt) {
7458+ if (pvt->channel == channel) {
7459+ ast_mutex_lock(&pvt->lock);
7460+ gsm_set_debug(pvt->gsm.modul, debug);
7461+ ast_mutex_unlock(&pvt->lock);
7462+ ast_cli(fd, "%s debugging on channel %d\n", debug ? "Enabled":"Disabled", channel);
7463+ return RESULT_SUCCESS;
7464+ }
7465+ pvt = pvt->next;
7466+ }
7467+
7468+ ast_cli(fd, "No GSM running on channel %d\n", channel);
7469+ return RESULT_SUCCESS;
7470+}
7471+
7472+
7473+
7474+static int handle_gsm_debug(int fd, int argc, char *argv[])
7475+{
7476+/* gsm debug channel <channel> */
7477+ int channel;
7478+ if (argc < 4) {
7479+ return RESULT_SHOWUSAGE;
7480+ }
7481+ channel = atoi(argv[3]);
7482+ return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_AT);
7483+}
7484+
7485+static int handle_gsm_no_debug(int fd, int argc, char *argv[])
7486+{
7487+/* gsm no debug channel <channel> */
7488+ int channel;
7489+ if (argc < 5) {
7490+ return RESULT_SHOWUSAGE;
7491+ }
7492+ channel = atoi(argv[4]);
7493+ return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_NONE);
7494+}
7495+
7496+static char zap_reset_help[] =
7497+ "Usage: zap reset span <span>\n"
7498+ " Reset/Restart a zaptel span\n";
7499+
7500+static char gsm_debug_help[] =
7501+ "Usage: gsm debug channel <channel>\n"
7502+ " Enables debugging on a given GSM channel\n";
7503+
7504+static char gsm_no_debug_help[] =
7505+ "Usage: gsm no debug channel <channel>\n"
7506+ " Disables debugging on a given GSM channel\n";
7507+
7508+static struct ast_cli_entry zap_gsm_cli[] = {
7509+ { { "zap", "reset", "span", NULL }, handle_zap_reset_span,
7510+ "Restart a zaptel span", zap_reset_help, complete_span_4 },
7511+ { { "gsm", "debug", "channel", NULL }, handle_gsm_debug,
7512+ "Enables GSM debugging on a channel", gsm_debug_help },
7513+ { { "gsm", "no", "debug", "channel", NULL }, handle_gsm_no_debug,
7514+ "Disables GSM debugging on a channel", gsm_no_debug_help},
7515+};
7516+
7517+
7518+
7519+static char gsm_send_pdu_help[] =
7520+ "Usage: gsm send pdu <channel> <pdu>\n"
7521+ " Sends a PDU on a GSM channel\n";
7522+
7523+
7524+
7525+static int handle_gsm_send_pdu(int fd, int argc, char *argv[])
7526+{
7527+/* gsm send sms <channel> <destination> <message> */
7528+ int channel;
7529+ struct zt_pvt *pvt = NULL;
7530+ if (argc < 5) {
7531+ return RESULT_SHOWUSAGE;
7532+ }
7533+ channel = atoi(argv[3]);
7534+ if (channel < 1) {
7535+ ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
7536+ return RESULT_SUCCESS;
7537+ }
7538+ pvt = iflist;
7539+ while (pvt) {
7540+ if (pvt->channel == channel) {
7541+ if (pvt->owner) {
7542+ ast_cli(fd, "Channel in use.\n");
7543+ return RESULT_FAILURE;
7544+ } else {
7545+ ast_mutex_lock(&pvt->lock);
7546+ gsm_sms_send_pdu(pvt->gsm.modul, argv[4]);
7547+ ast_mutex_unlock(&pvt->lock);
7548+ return RESULT_SUCCESS;
7549+ }
7550+ }
7551+ pvt = pvt->next;
7552+ }
7553+
7554+ return RESULT_SUCCESS;
7555+}
7556+
7557+static struct ast_cli_entry gsm_send_pdu = {
7558+ { "gsm", "send", "pdu", NULL }, handle_gsm_send_pdu, "Sends a SM on a GSM channel", gsm_send_pdu_help, complete_span_4 };
7559+
7560+
7561+static char gsm_send_sms_help[] =
7562+ "Usage: gsm send sms <channel> <destination> <message>\n"
7563+ " Sends a SM on a GSM channel\n";
7564+
7565+
7566+static int handle_gsm_send_sms(int fd, int argc, char *argv[])
7567+{
7568+/* gsm send sms <channel> <destination> <message> */
7569+ int channel;
7570+ struct zt_pvt *pvt = NULL;
7571+ if (argc < 6) {
7572+ return RESULT_SHOWUSAGE;
7573+ }
7574+ channel = atoi(argv[3]);
7575+ if (channel < 1) {
7576+ ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
7577+ return RESULT_SUCCESS;
7578+ }
7579+ pvt = iflist;
7580+ while (pvt) {
7581+ if (pvt->channel == channel) {
7582+ if (pvt->owner) {
7583+ ast_cli(fd, "Channel in use.\n");
7584+ return RESULT_FAILURE;
7585+ } else {
7586+ ast_mutex_lock(&pvt->lock);
7587+ gsm_sms_send_text(pvt->gsm.modul, argv[4], argv[5]);
7588+ ast_mutex_unlock(&pvt->lock);
7589+ return RESULT_SUCCESS;
7590+ }
7591+ }
7592+ pvt = pvt->next;
7593+ }
7594+
7595+ return RESULT_SUCCESS;
7596+}
7597+
7598+static int zt_gsm_sendtext(struct ast_channel *chan, const char * dest, const char *text, int ispdu) {
7599+ struct zt_pvt *pvt = NULL;
7600+ char *c = NULL;
7601+ pvt = chan->tech_pvt;
7602+
7603+ if (!pvt) return -1;
7604+
7605+ /* parse dialstring */
7606+ c = strrchr(dest, '/');
7607+ if (c)
7608+ c++;
7609+ else
7610+ c = (char *)dest;
7611+
7612+ ast_mutex_lock(&pvt->lock);
7613+ if (ispdu) {
7614+ gsm_sms_send_pdu(pvt->gsm.modul, (char *)text);
7615+ } else {
7616+ gsm_sms_send_text(pvt->gsm.modul, c, (char *)text);
7617+ }
7618+ ast_mutex_unlock(&pvt->lock);
7619+ gsm_wait(pvt->gsm.modul);
7620+ return 0;
7621+}
7622+
7623+static struct ast_cli_entry gsm_send_sms = {
7624+ { "gsm", "send", "sms", NULL }, handle_gsm_send_sms, "Sends a SM on a GSM channel", gsm_send_sms_help, complete_span_4 };
7625+
7626+static char gsm_show_status_help[] =
7627+ "Usage: gsm show status <channel>>\n"
7628+ " Displays status information about the GSM channel.\n";
7629+
7630+
7631+static int handle_gsm_show_status(int fd, int argc, char *argv[])
7632+{
7633+ int channel;
7634+ struct zt_pvt *pvt = NULL;
7635+ if (argc < 4) {
7636+ return RESULT_SHOWUSAGE;
7637+ }
7638+ channel = atoi(argv[3]);
7639+ if (channel < 1) {
7640+ ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
7641+ return RESULT_SUCCESS;
7642+ }
7643+ pvt = iflist;
7644+ while (pvt) {
7645+ if (pvt->channel == channel) {
7646+ if (pvt->owner) {
7647+ ast_cli(fd, "Channel in use.\n");
7648+ return RESULT_FAILURE;
7649+ } else {
7650+ ast_mutex_lock(&pvt->lock);
7651+ gsm_request_status(pvt->gsm.modul);
7652+ ast_mutex_unlock(&pvt->lock);
7653+ return RESULT_SUCCESS;
7654+ }
7655+ }
7656+ pvt = pvt->next;
7657+ }
7658+
7659+ return RESULT_SUCCESS;
7660+}
7661+
7662+static struct ast_cli_entry gsm_show_status = {
7663+ { "gsm", "show", "status", NULL }, handle_gsm_show_status, "Displays status information about the GSM channel.", gsm_show_status_help, complete_span_4 };
7664+
7665+#endif /* HAVE_GSMAT */
7666+
7667 static int app_zapEC(struct ast_channel *chan, void *data)
7668 {
7669 int res=-1;
7670@@ -11489,6 +12069,12 @@ static int __unload_module(void)
7671 ast_unregister_application(zapCD_app);
7672 ast_unregister_application(zapInband_app);
7673 #endif
7674+#ifdef HAVE_GSMAT
7675+ ast_cli_unregister_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
7676+ ast_cli_unregister(&gsm_send_sms);
7677+ ast_cli_unregister(&gsm_send_pdu);
7678+ ast_cli_unregister(&gsm_show_status);
7679+#endif
7680 ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
7681 ast_unregister_application(zapEC_app);
7682 ast_manager_unregister( "ZapDialOffhook" );
7683@@ -12009,6 +12595,11 @@ static int process_zap(struct zt_chan_co
7684 confp->chan.radio = 0;
7685 confp->pri.nodetype = BRI_CPE;
7686 #endif
7687+#ifdef HAVE_GSMAT
7688+ } else if (!strcasecmp(v->value, "gsm")) {
7689+ confp->chan.sig = SIG_GSM;
7690+ confp->chan.radio = 0;
7691+#endif
7692 } else {
7693 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
7694 }
7695@@ -12151,6 +12742,10 @@ static int process_zap(struct zt_chan_co
7696 ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
7697 } else if (!strcasecmp(v->name, "withheldcid")) {
7698 ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
7699+ } else if (!strcasecmp(v->name, "pin")) {
7700+ ast_copy_string(gsm_modem_pin, v->value, sizeof(gsm_modem_pin) - 1);
7701+ } else if (!strcasecmp(v->name, "exten")) {
7702+ ast_copy_string(gsm_modem_exten, v->value, sizeof(gsm_modem_exten) - 1);
7703 } else if (!strcasecmp(v->name, "resetinterval")) {
7704 if (!strcasecmp(v->value, "never"))
7705 confp->pri.resetinterval = -1;
7706@@ -12506,6 +13101,10 @@ static int load_module(void)
7707 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
7708 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
7709 #endif
7710+#ifdef HAVE_GSMAT
7711+ gsm_set_error(zt_gsm_error);
7712+ gsm_set_message(zt_gsm_message);
7713+#endif
7714 res = setup_zap(0);
7715 /* Make sure we can register our Zap channel type */
7716 if (res)
7717@@ -12524,6 +13123,12 @@ static int load_module(void)
7718 #endif
7719 ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
7720 ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
7721+#ifdef HAVE_GSMAT
7722+ ast_cli_register(&gsm_send_sms);
7723+ ast_cli_register(&gsm_send_pdu);
7724+ ast_cli_register(&gsm_show_status);
7725+ ast_cli_register_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
7726+#endif
7727
7728 memset(round_robin, 0, sizeof(round_robin));
7729 ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
7730@@ -12537,7 +13142,66 @@ static int load_module(void)
7731 return res;
7732 }
7733
7734-static int zt_sendtext(struct ast_channel *c, const char *text)
7735+#ifdef HAVE_PRI
7736+static int zt_tdd_sendtext(struct ast_channel *c, const char *text);
7737+
7738+static int zt_pri_sendtext(struct ast_channel *c, const char *text) {
7739+ struct zt_pvt *p = c->tech_pvt;
7740+ if (!p) return -1;
7741+ if (!p->pri) return -1;
7742+ if (strlen(text)) {
7743+ if (p->pri) {
7744+ if (!pri_grab(p, p->pri)) {
7745+ // ast_log(LOG_NOTICE, "Sending Display IE '%s'\n", text);
7746+ pri_information_display(p->pri->pri,p->call,(char *)text);
7747+ pri_rel(p->pri);
7748+ } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7749+ }
7750+ }
7751+ return 0;
7752+}
7753+#endif
7754+
7755+static int zt_sendtext(struct ast_channel *c, const char *text) {
7756+ struct zt_pvt *p = c->tech_pvt;
7757+ if (!p) return -1;
7758+ if (p->sig == SIG_PRI) {
7759+#ifdef HAVE_PRI
7760+ return zt_pri_sendtext(c, text);
7761+#endif
7762+ } else if (p->sig == SIG_GSM) {
7763+ } else {
7764+ return zt_tdd_sendtext(c, text);
7765+ }
7766+ return -1;
7767+}
7768+
7769+static int zt_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu) {
7770+struct zt_pvt *p = c->tech_pvt;
7771+ if (!p) return -1;
7772+ if (p->sig == SIG_PRI) {
7773+#ifdef HAVE_PRI
7774+ if (ispdu) {
7775+ ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP ISDN channel\n");
7776+ return -1;
7777+ }
7778+ return zt_pri_sendtext(c, text);
7779+#endif
7780+ } else if (p->sig == SIG_GSM) {
7781+#ifdef HAVE_GSMAT
7782+ return zt_gsm_sendtext(c, dest, text, ispdu);
7783+#endif
7784+ } else {
7785+ if (ispdu) {
7786+ ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP channel\n");
7787+ return -1;
7788+ }
7789+ return zt_tdd_sendtext(c, text);
7790+ }
7791+ return -1;
7792+}
7793+
7794+static int zt_tdd_sendtext(struct ast_channel *c, const char *text)
7795 {
7796 #define END_SILENCE_LEN 400
7797 #define HEADER_MS 50
7798--- a/configure.ac
7799+++ b/configure.ac
7800@@ -178,6 +178,7 @@ AST_EXT_LIB_SETUP([CAP], [POSIX 1.e capa
7801 AST_EXT_LIB_SETUP([CURSES], [curses], [curses])
7802 AST_EXT_LIB_SETUP([GNUTLS], [GNU TLS support (used for iksemel only)], [gnutls])
7803 AST_EXT_LIB_SETUP([GSM], [GSM], [gsm], [, or 'internal'])
7804+AST_EXT_LIB_SETUP([GSMAT], [GSMAT], [GSM AT command signalling], [gsmat])
7805 AST_EXT_LIB_SETUP([IKSEMEL], [Iksemel Jabber Library], [iksemel])
7806 AST_EXT_LIB_SETUP([IMAP_TK], [UW IMAP Toolkit], [imap])
7807 AST_EXT_LIB_SETUP([ISDNNET], [ISDN4Linux Library], [isdnnet])
7808--- a/configure
7809+++ b/configure
7810@@ -26600,6 +26600,188 @@ echo "$as_me: *** without explicitly spe
7811 fi
7812 fi
7813
7814+{ echo "$as_me:$LINENO: checking for ${GSMAT_DIR}/include/libgsmat.h" >&5
7815+echo $ECHO_N "checking for ${GSMAT_DIR}/include/libgsmat.h... $ECHO_C" >&6; }
7816+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
7817+ echo $ECHO_N "(cached) $ECHO_C" >&6
7818+else
7819+ eval "$as_ac_Header=\$ac_header_preproc"
7820+fi
7821+ac_res=`eval echo '${'$as_ac_Header'}'`
7822+ { echo "$as_me:$LINENO: result: $ac_res" >&5
7823+echo "${ECHO_T}$ac_res" >&6; }
7824+
7825+if test `eval echo '${'$as_ac_Header'}'` = yes; then
7826+ GSMAT_HEADER_FOUND=1
7827+else
7828+ GSMAT_HEADER_FOUND=0
7829+fi
7830+
7831+
7832+
7833+ if test "${GSMAT_HEADER_FOUND}" = "yes"; then
7834+ GSMAT_LIB="-lgsmat "
7835+ GSMAT_HEADER_FOUND="1"
7836+ if test "x${GSMAT_DIR}" != "x"; then
7837+ GSMAT_LIB="${pbxlibdir} ${GSMAT_LIB}"
7838+ GSMAT_INCLUDE="-I${GSMAT_DIR}/include"
7839+ fi
7840+ CPPFLAGS="${saved_cppflags}"
7841+ else
7842+ if test "xlibgsmat.h" != "x" ; then
7843+ if test "${ac_cv_header_libpri_h+set}" = set; then
7844+ { echo "$as_me:$LINENO: checking for libgsmat.h" >&5
7845+echo $ECHO_N "checking for libgsmat.h... $ECHO_C" >&6; }
7846+if test "${ac_cv_header_libgsmat_h+set}" = set; then
7847+ echo $ECHO_N "(cached) $ECHO_C" >&6
7848+fi
7849+{ echo "$as_me:$LINENO: result: $ac_cv_header_libgsmat_h" >&5
7850+echo "${ECHO_T}$ac_cv_header_libgsmat_h" >&6; }
7851+else
7852+ # Is the header compilable?
7853+{ echo "$as_me:$LINENO: checking libgsmat.h usability" >&5
7854+echo $ECHO_N "checking libgsmat.h usability... $ECHO_C" >&6; }
7855+cat >conftest.$ac_ext <<_ACEOF
7856+/* confdefs.h. */
7857+_ACEOF
7858+cat confdefs.h >>conftest.$ac_ext
7859+cat >>conftest.$ac_ext <<_ACEOF
7860+/* end confdefs.h. */
7861+$ac_includes_default
7862+#include <libgsmat.h>
7863+_ACEOF
7864+rm -f conftest.$ac_objext
7865+if { (ac_try="$ac_compile"
7866+case "(($ac_try" in
7867+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
7868+ *) ac_try_echo=$ac_try;;
7869+esac
7870+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
7871+ (eval "$ac_compile") 2>conftest.er1
7872+ ac_status=$?
7873+ grep -v '^ *+' conftest.er1 >conftest.err
7874+ rm -f conftest.er1
7875+ cat conftest.err >&5
7876+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
7877+ (exit $ac_status); } && {
7878+ test -z "$ac_c_werror_flag" ||
7879+ test ! -s conftest.err
7880+ } && test -s conftest.$ac_objext; then
7881+ ac_header_compiler=yes
7882+else
7883+ echo "$as_me: failed program was:" >&5
7884+sed 's/^/| /' conftest.$ac_ext >&5
7885+
7886+ ac_header_compiler=no
7887+fi
7888+
7889+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
7890+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
7891+echo "${ECHO_T}$ac_header_compiler" >&6; }
7892+
7893+# Is the header present?
7894+{ echo "$as_me:$LINENO: checking libgsmat.h presence" >&5
7895+echo $ECHO_N "checking libgsmat.h presence... $ECHO_C" >&6; }
7896+cat >conftest.$ac_ext <<_ACEOF
7897+/* confdefs.h. */
7898+_ACEOF
7899+cat confdefs.h >>conftest.$ac_ext
7900+cat >>conftest.$ac_ext <<_ACEOF
7901+/* end confdefs.h. */
7902+#include <libgsmat.h>
7903+_ACEOF
7904+if { (ac_try="$ac_cpp conftest.$ac_ext"
7905+case "(($ac_try" in
7906+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
7907+ *) ac_try_echo=$ac_try;;
7908+esac
7909+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
7910+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
7911+ ac_status=$?
7912+ grep -v '^ *+' conftest.er1 >conftest.err
7913+ rm -f conftest.er1
7914+ cat conftest.err >&5
7915+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
7916+ (exit $ac_status); } >/dev/null && {
7917+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
7918+ test ! -s conftest.err
7919+ }; then
7920+ ac_header_preproc=yes
7921+else
7922+ echo "$as_me: failed program was:" >&5
7923+sed 's/^/| /' conftest.$ac_ext >&5
7924+
7925+ ac_header_preproc=no
7926+fi
7927+
7928+rm -f conftest.err conftest.$ac_ext
7929+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
7930+echo "${ECHO_T}$ac_header_preproc" >&6; }
7931+
7932+# So? What about this header?
7933+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
7934+ yes:no: )
7935+ { echo "$as_me:$LINENO: WARNING: libgsmat.h: accepted by the compiler, rejected by the preprocessor!" >&5
7936+echo "$as_me: WARNING: libgsmat.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
7937+ { echo "$as_me:$LINENO: WARNING: libgsmat.h: proceeding with the compiler's result" >&5
7938+echo "$as_me: WARNING: libgsmat.h: proceeding with the compiler's result" >&2;}
7939+ ac_header_preproc=yes
7940+ ;;
7941+ no:yes:* )
7942+ { echo "$as_me:$LINENO: WARNING: libgsmat.h: present but cannot be compiled" >&5
7943+echo "$as_me: WARNING: libgsmat.h: present but cannot be compiled" >&2;}
7944+ { echo "$as_me:$LINENO: WARNING: libgsmat.h: check for missing prerequisite headers?" >&5
7945+echo "$as_me: WARNING: libgsmat.h: check for missing prerequisite headers?" >&2;}
7946+ { echo "$as_me:$LINENO: WARNING: libgsmat.h: see the Autoconf documentation" >&5
7947+echo "$as_me: WARNING: libgsmat.h: see the Autoconf documentation" >&2;}
7948+ { echo "$as_me:$LINENO: WARNING: libgsmat.h: section \"Present But Cannot Be Compiled\"" >&5
7949+echo "$as_me: WARNING: libgsmat.h: section \"Present But Cannot Be Compiled\"" >&2;}
7950+ { echo "$as_me:$LINENO: WARNING: libgsmat.h: proceeding with the preprocessor's result" >&5
7951+echo "$as_me: WARNING: libgsmat.h: proceeding with the preprocessor's result" >&2;}
7952+ { echo "$as_me:$LINENO: WARNING: libgsmat.h: in the future, the compiler will take precedence" >&5
7953+echo "$as_me: WARNING: libgsmat.h: in the future, the compiler will take precedence" >&2;}
7954+
7955+ ;;
7956+esac
7957+{ echo "$as_me:$LINENO: checking for libgsmat.h" >&5
7958+echo $ECHO_N "checking for libgsmat.h... $ECHO_C" >&6; }
7959+if test "${ac_cv_header_libgsmat_h+set}" = set; then
7960+ echo $ECHO_N "(cached) $ECHO_C" >&6
7961+else
7962+ ac_cv_header_libgsmat_h=$ac_header_preproc
7963+fi
7964+{ echo "$as_me:$LINENO: result: $ac_cv_header_libgsmat_h" >&5
7965+echo "${ECHO_T}$ac_cv_header_libgsmat_h" >&6; }
7966+
7967+fi
7968+
7969+
7970+ fi
7971+ fi
7972+ if test "x${GSMAT_HEADER_FOUND}" = "x0" ; then
7973+ if test -n "${GSMAT_MANDATORY}" ;
7974+ then
7975+ { echo "$as_me:$LINENO: ***" >&5
7976+echo "$as_me: ***" >&6;}
7977+ { echo "$as_me:$LINENO: *** It appears that you do not have the GSMAT development package installed." >&5
7978+echo "$as_me: *** It appears that you do not have the GSMAT development package installed." >&6;}
7979+ { echo "$as_me:$LINENO: *** Please install it to include ${GSMAT_DESCRIP} support, or re-run configure" >&5
7980+echo "$as_me: *** Please install it to include ${GSMAT_DESCRIP} support, or re-run configure" >&6;}
7981+ { echo "$as_me:$LINENO: *** without explicitly specifying --with-${GSMAT_OPTION}" >&5
7982+echo "$as_me: *** without explicitly specifying --with-${GSMAT_OPTION}" >&6;}
7983+ exit 1
7984+ fi
7985+ GSMAT_LIB=""
7986+ GSMAT_INCLUDE=""
7987+ PBX_GSMAT=0
7988+ else
7989+ PBX_GSMAT=1
7990+
7991+cat >>confdefs.h <<_ACEOF
7992+#define HAVE_GSMAT 1
7993+_ACEOF
7994+
7995+fi
7996
7997 if test "${USE_PWLIB}" != "no"; then
7998 if test -n "${PWLIB_DIR}"; then
This page took 1.291217 seconds and 4 git commands to generate.