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