3 @@ -4,6 +4,8 @@ and the Asterisk.org developer community
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 ================================================================
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.
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.
32 +-- Junghanns.NET (Primary author of BRIstuff)
33 + http://www.junghanns.net
35 + * quadBRI PCI ISDN - 4port BRI ISDN interface, supports NT and TE mode
37 + * octoBRI PCI ISDN - 8port BRI ISDN interface, supports NT and TE mode
39 + * singleE1 PCI ISDN - Single E1 interface
41 + * doubleE1 PCI ISDN - Double E1 interface
43 + * uno/duo/quad GSM PCI - 1/2/4 channel GSM interface cards
45 Non-zaptel compatible hardware
46 ==============================
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"
56 #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
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));
66 /* no asterisk.conf? no problem, use buildtime config! */
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);
77 --- a/include/asterisk/agi.h
78 +++ b/include/asterisk/agi.h
79 @@ -29,7 +29,8 @@ extern "C" {
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 */
92 * the project provides a web site, mailing lists and IRC
93 * channels for your use.
95 + * Copyright (C) 2005 Junghanns.NET GmbH
96 + * Klaus-Peter Junghanns <kpj@junghanns.net>
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
103 static char *app = "AGI";
105 +static char *xapp = "XAGI";
107 static char *eapp = "EAGI";
109 static char *deadapp = "DeadAGI";
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";
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;
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)
146 sigset_t signal_set, old_set;
147 @@ -287,6 +296,33 @@ static enum agi_result launch_script(cha
148 return AGI_RESULT_FAILURE;
152 + if (pipe(audio2)) {
153 + ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
160 + return AGI_RESULT_FAILURE;
162 + res = fcntl(audio2[0], F_GETFL);
164 + res = fcntl(audio2[0], F_SETFL, res | O_NONBLOCK);
166 + ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
175 + return AGI_RESULT_FAILURE;
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
183 close(STDERR_FILENO + 1);
186 + dup2(audio2[1], STDERR_FILENO + 2);
188 + close(STDERR_FILENO + 2);
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
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++)
202 @@ -357,12 +398,19 @@ static enum agi_result launch_script(cha
209 /* close what we're not using in the parent */
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");
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;
241 @@ -596,7 +644,7 @@ static int handle_streamfile(struct ast_
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
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
261 /* If the user didnt press a key, wait for digitTimeout*/
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) )
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);
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;
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
288 return RESULT_SHOWUSAGE;
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
297 return RESULT_SHOWUSAGE;
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
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;
313 @@ -1833,8 +1881,13 @@ static enum agi_result run_agi(struct as
315 enum agi_result returnstatus = AGI_RESULT_SUCCESS;
317 + struct ast_frame fr;
318 char buf[AGI_BUF_LEN];
319 + char audiobuf[AGI_BUF_LEN];
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;
331 - setup_env(chan, request, agi->fd, (agi->audio > -1));
332 + if (agi->audio_out > -1) {
335 + if (agi->audio_in > -1) {
338 + setup_env(chan, request, agi->fd, enhanced);
339 + fds[0] = agi->ctrl;
340 + fds[1] = agi->audio_in;
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);
347 + c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
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
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);
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);
375 size_t len = sizeof(buf);
378 @@ -1914,6 +1989,7 @@ static enum agi_result run_agi(struct as
379 if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
385 ast_log(LOG_WARNING, "No channel, no fd?\n");
386 @@ -2022,6 +2098,7 @@ static int agi_exec_full(struct ast_chan
394 @@ -2047,12 +2124,13 @@ static int agi_exec_full(struct ast_chan
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) {
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
416 ast_unreplace_sigchld();
418 ast_module_user_remove(u);
419 @@ -2110,6 +2190,35 @@ static int eagi_exec(struct ast_channel
423 +static int xagi_exec(struct ast_channel *chan, void *data)
425 + int readformat, writeformat;
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);
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);
440 + res = agi_exec_full(chan, data, 2, 0);
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));
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));
452 static int deadagi_exec(struct ast_channel *chan, void *data)
454 if (!ast_check_hangup(chan))
455 @@ -2165,6 +2274,7 @@ static int unload_module(void)
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);
472 +++ b/agi/xagi-test.c
475 + * Asterisk -- A telephony toolkit for Linux.
477 + * XAGI sample script
479 + * Copyright (C) 2005 Junghanns.NET GmbH
480 + * Klaus-Peter Junghanns <kpj@junghanns.net>
482 + * based on eagi-test.c
484 + * This program is free software, distributed under the terms of
485 + * the GNU General Public License
493 +#include <sys/select.h>
495 +#include <solaris-compat/compat.h>
498 +#define AUDIO_FILENO_IN (STDERR_FILENO + 1)
499 +#define AUDIO_FILENO_OUT (STDERR_FILENO + 2)
501 +static int read_environment(void)
505 + /* Read environment */
507 + fgets(buf, sizeof(buf), stdin);
510 + buf[strlen(buf) - 1] = '\0';
511 + /* Check for end of environment */
514 + val = strchr(buf, ':');
516 + fprintf(stderr, "Invalid environment: '%s'\n", buf);
523 + // fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val);
525 + /* Load into normal environment */
526 + setenv(buf, val, 1);
529 + /* Never reached */
533 +static void app_echo(void)
538 + static char astresp[256];
539 + char audiobuf[16000]; /* 1 second of audio */
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);
547 + fprintf(stderr, "Error in select: %s\n", strerror(errno));
550 + if (FD_ISSET(STDIN_FILENO, &fds)) {
551 + fgets(astresp, sizeof(astresp), stdin);
555 + astresp[strlen(astresp) - 1] = '\0';
556 + fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
559 + if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
560 + /* what goes in.... */
561 + res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
564 + /* must come out */
565 + write(AUDIO_FILENO_OUT, audiobuf, bytes);
571 +static char *wait_result(void)
575 + static char astresp[256];
576 + char audiobuf[4096];
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);
584 + fprintf(stderr, "Error in select: %s\n", strerror(errno));
587 + if (FD_ISSET(STDIN_FILENO, &fds)) {
588 + fgets(astresp, sizeof(astresp), stdin);
590 + fprintf(stderr, "Got hungup on apparently\n");
593 + astresp[strlen(astresp) - 1] = '\0';
594 + fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
597 + if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
598 + res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
599 + /* drop it, like it's hot */
605 +static char *run_command(char *command)
607 + fprintf(stdout, "%s\n", command);
608 + return wait_result();
612 +static int run_script(void)
615 + res = run_command("STREAM FILE demo-echotest \"\"");
617 + fprintf(stderr, "Failed to execute command\n");
624 +int main(int argc, char *argv[])
629 + /* Setup stdin/stdout for line buffering */
631 + setlinebuf(stdout);
632 + if (read_environment()) {
633 + fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
636 + tmp = getenv("agi_enhanced");
638 + if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
642 + fprintf(stderr, "No XAGI services available. Use XAGI, not AGI or EAGI\n");
653 .PHONY: clean all uninstall
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
658 ifeq ($(OSARCH),SunOS)
660 @@ -38,7 +38,7 @@ uninstall:
661 for x in $(AGIS); do rm -f $(DESTDIR)$(AGI_DIR)/$$x ; done
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
670 +++ b/apps/app_segfault.c
673 + * Segfault application
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.)
679 + * Copyright (C) 2005 Junghanns.NET GmbH
680 + * Klaus-Peter Junghanns <kpj@junghanns.net>
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!
687 +#include "asterisk.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>
700 +static char *app = "Segfault";
702 +static char *synopsis = "This application will crash Asterisk with a segmentation fault.";
704 +static char *descrip =
705 +" Segfault(): Crash with a segfault. Never returns nufin.\n";
707 +static int segfault_exec(struct ast_channel *chan, void *data)
709 + ((char *)0)[0] = 0;
713 +static int unload_module(void)
715 + return ast_unregister_application(app);
718 +static int load_module(void)
720 + return ast_register_application(app, segfault_exec, synopsis, descrip);
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,
727 --- a/apps/app_directed_pickup.c
728 +++ b/apps/app_directed_pickup.c
729 @@ -45,7 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
731 #define PICKUPMARK "PICKUPMARK"
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"
739 +++ b/apps/app_pickup.c
742 + * Asterisk -- A telephony toolkit for Linux.
744 + * Pickup, channel independent call pickup
746 + * Copyright (C) 2004, Junghanns.NET GmbH
748 + * Klaus-Peter Junghanns <kpj@junghanns.net>
750 + * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
752 + * This program is free software, distributed under the terms of
753 + * the GNU General Public License
756 +#include "asterisk.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>
774 +static char *app = "PickUp";
776 +static char *synopsis = "Channel independent call pickup.";
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";
782 +static char *app2 = "Steal";
784 +static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
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";
790 +static char *app3 = "PickDown";
792 +static char *synopsis3 = "Channel independent call pickdown.";
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";
798 +static char *app4 = "PickupChan";
800 +static char *synopsis4 = "Channel independent call pickup.";
802 +static char *descrip4 =
803 +" PickupChan(Technology/resource[&Technology2/resource2...]): Tries to pickup the first ringing channel in the parameter list.\n";
805 +static char *app5 = "StealChan";
807 +static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
809 +static char *descrip5 =
810 +" StealChan(Technology/resource[&Technology2/resource2...]): Tries to steal the first ringing channel in the parameter list.\n";
813 +static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
814 + struct ast_channel *cur;
816 + cur = ast_channel_walk_locked(NULL);
818 + if ((cur != chan) &&
819 + (pickupgroup & cur->callgroup) &&
820 + (cur->_state == chanstate)) {
823 + ast_mutex_unlock(&cur->lock);
824 + cur = ast_channel_walk_locked(cur);
827 + if(option_verbose > 2) {
828 + if (chanstate == AST_STATE_RINGING) {
830 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
832 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
835 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
839 + if (chan->_state != AST_STATE_UP) {
842 + if (ast_channel_masquerade(cur, chan)) {
843 + ast_log(LOG_ERROR, "unable to masquerade\n");
845 + ast_mutex_unlock(&cur->lock);
846 + ast_mutex_unlock(&chan->lock);
848 + cur->_softhangup = AST_SOFTHANGUP_DEV;
849 + ast_mutex_unlock(&cur->lock);
852 + if(option_verbose > 2) {
853 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
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];
865 + cur = ast_channel_walk_locked(NULL);
866 + strncpy(channels, (char *)data, sizeof(channels) - 1);
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, '-');
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);
884 + ast_mutex_unlock(&cur->lock);
885 + cur = ast_channel_walk_locked(cur);
888 + if(option_verbose > 2) {
889 + if (chanstate == AST_STATE_RINGING) {
891 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
893 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
896 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
900 + if (chan->_state != AST_STATE_UP) {
903 + if (ast_channel_masquerade(cur, chan)) {
904 + ast_log(LOG_ERROR, "unable to masquerade\n");
906 + ast_mutex_unlock(&cur->lock);
907 + ast_mutex_unlock(&chan->lock);
909 + cur->_softhangup = AST_SOFTHANGUP_DEV;
910 + ast_mutex_unlock(&cur->lock);
913 + if(option_verbose > 2) {
914 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
921 +static int pickup_exec(struct ast_channel *chan, void *data)
924 + unsigned int pickupgroup=0;
925 + struct ast_module_user *u;
926 + if (!data || !strlen(data)) {
927 + pickupgroup = chan->pickupgroup;
929 + pickupgroup = ast_get_group(data);
931 + u = ast_module_user_add(chan);
933 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
937 + ast_module_user_remove(u);
941 +static int steal_exec(struct ast_channel *chan, void *data)
944 + unsigned int pickupgroup=0;
945 + struct ast_module_user *u;
946 + if (!data || !strlen(data)) {
947 + pickupgroup = chan->pickupgroup;
949 + pickupgroup = ast_get_group(data);
951 + u = ast_module_user_add(chan);
953 + res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
957 + ast_module_user_remove(u);
961 +static int pickdown_exec(struct ast_channel *chan, void *data)
964 + unsigned int pickupgroup=0;
965 + struct ast_module_user *u;
966 + if (!data || !strlen(data)) {
967 + pickupgroup = chan->pickupgroup;
969 + pickupgroup = ast_get_group(data);
971 + u = ast_module_user_add(chan);
973 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
977 + ast_module_user_remove(u);
981 +static int pickupchan_exec(struct ast_channel *chan, void *data) {
983 + struct ast_module_user *u;
985 + ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
988 + u = ast_module_user_add(chan);
990 + res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
994 + ast_module_user_remove(u);
998 +static int stealchan_exec(struct ast_channel *chan, void *data)
1001 + struct ast_module_user *u;
1003 + ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
1007 + u = ast_module_user_add(chan);
1009 + res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
1013 + ast_module_user_remove(u);
1018 +static int unload_module(void)
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);
1028 +static int load_module(void)
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);
1037 +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PickUp/PickDown/Steal/PickupChan/StealChan",
1038 + .load = load_module,
1039 + .unload = unload_module,
1042 +++ b/apps/app_devstate.c
1045 + * Devstate application
1047 + * Since we like the snom leds so much, a little app to
1048 + * light the lights on the snom on demand ....
1050 + * Copyright (C) 2005, Druid Software
1052 + * This program is free software, distributed under the terms of
1053 + * the GNU General Public License
1056 +#include "asterisk.h"
1058 +#include <stdlib.h>
1059 +#include <unistd.h>
1060 +#include <string.h>
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"
1075 +static char type[] = "DS";
1076 +static char tdesc[] = "Application for sending device state messages";
1078 +static char app[] = "Devstate";
1080 +static char synopsis[] = "Generate a device state change event given the input parameters";
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";
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";
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 };
1093 +static int devstate_cli(int fd, int argc, char *argv[])
1095 + char devName[128];
1097 + return RESULT_SHOWUSAGE;
1099 + if (ast_db_put("DEVSTATES", argv[1], argv[2]))
1101 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1103 + snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
1104 + ast_device_state_changed_literal(devName);
1105 + return RESULT_SUCCESS;
1108 +static int devstate_exec(struct ast_channel *chan, void *data)
1110 + char *device, *state, *info;
1111 + char devName[128];
1112 + struct ast_module_user *u;
1115 + if (!(info = ast_strdupa(data))) {
1116 + ast_log(LOG_WARNING, "Unable to dupe data :(\n");
1120 + u = ast_module_user_add(chan);
1122 + state = strchr(info, '|');
1129 + ast_log(LOG_DEBUG, "No state argument supplied\n");
1133 + if (ast_db_put("DEVSTATES", device, state))
1135 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1138 + snprintf(devName, sizeof(devName), "DS/%s", device);
1139 + ast_device_state_changed_literal(devName);
1141 + ast_module_user_remove(u);
1146 +static int ds_devicestate(void *data)
1148 + char *dest = data;
1149 + char stateStr[16];
1150 + if (ast_db_get("DEVSTATES", dest, stateStr, sizeof(stateStr)))
1152 + ast_log(LOG_DEBUG, "ds_devicestate couldnt get state in astdb\n");
1157 + ast_log(LOG_DEBUG, "ds_devicestate dev=%s returning state %d\n",
1158 + dest, atoi(stateStr));
1159 + return (atoi(stateStr));
1163 +static struct ast_channel_tech devstate_tech = {
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,
1178 + .exception = NULL,
1181 + .setoption = NULL,
1184 +static char mandescr_devstate[] =
1185 +"Description: Put a value into astdb\n"
1191 +static int action_devstate(struct mansession *s, const struct message *m)
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] = "";
1199 + if (!strlen(devstate)) {
1200 + astman_send_error(s, m, "No Devstate specified");
1203 + if (!strlen(value)) {
1204 + astman_send_error(s, m, "No Value specified");
1207 + if (!ast_strlen_zero(id))
1208 + snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
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);
1215 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1216 + astman_append(s, "Response: Failed\r\n%s\r\n", idText);
1221 +static int load_module(void)
1223 + if (ast_channel_register(&devstate_tech)) {
1224 + ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
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);
1232 +static int unload_module(void)
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);
1244 +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Devstate Application");
1247 +++ b/configs/watchdog.conf.sample
1250 +; Configuration file for res_watchdog
1252 +; type = isdnguard | watchdog
1253 +; device = /dev/...
1254 +; interval = interval to trigger the watchdog in ms
1256 +;[ISDNguard-direct]
1258 +;device = /dev/ttyS0
1261 +;[ISDNguard-with-daemon]
1263 +;device = /var/run/guard.ctl
1268 +;device = /dev/watchdog
1272 +++ b/res/res_watchdog.c
1275 + * Asterisk -- A telephony toolkit for Linux.
1277 + * Resource to make watchdogs happy
1279 + * Copyright (C) 2005, Junghanns.NET GmbH
1281 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1283 + * This program is free software, distributed under the terms of
1284 + * the GNU General Public License
1287 +#include "asterisk.h"
1288 +#include <stdlib.h>
1290 +#include <unistd.h>
1291 +#include <string.h>
1292 +#include <stdlib.h>
1294 +#include <sys/time.h>
1295 +#include <sys/signal.h>
1296 +#include <netinet/in.h>
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>
1314 +static struct watchdog_pvt *watchdogs = NULL;
1316 +typedef struct watchdog_pvt {
1321 + pthread_t watchdog_thread;
1322 + struct watchdog_pvt *next;
1325 +static void *do_watchdog_thread(void *data) {
1326 + struct watchdog_pvt *woof = (struct watchdog_pvt *)data;
1329 + write(woof->fd, "PING\n", 5);
1331 + usleep(woof->interval * 1000);
1337 +static int load_module(void)
1340 + const char *cat, *utype, *udevice, *uinterval;
1341 + struct ast_config *cfg;
1342 + struct watchdog_pvt *woof = NULL;
1344 + cfg = ast_config_load("watchdog.conf");
1346 + cat = ast_category_browse(cfg, NULL);
1348 + cat = ast_category_browse(cfg, cat);
1349 + utype = ast_variable_retrieve(cfg, cat, "type");
1351 + ast_log(LOG_NOTICE, "type = %s\n", utype);
1353 + udevice = ast_variable_retrieve(cfg, cat, "device");
1355 + ast_log(LOG_NOTICE, "device = %s\n", udevice);
1357 + uinterval = ast_variable_retrieve(cfg, cat, "interval");
1358 +/* if (uinterval) {
1359 + ast_log(LOG_NOTICE, "interval = %s\n", uinterval);
1361 + if (uinterval && udevice && utype) {
1362 + woof = malloc(sizeof(struct watchdog_pvt));
1364 + ast_log(LOG_ERROR, "unable to malloc!\n");
1367 + memset(woof, 0x0, sizeof(struct watchdog_pvt));
1368 + strncpy(woof->device, udevice, sizeof(woof->device) - 1);
1370 + woof->interval = atoi(uinterval);;
1371 + woof->next = watchdogs;
1373 + woof->fd = open(woof->device, O_WRONLY | O_SYNC);
1375 + if (!strncmp(utype, "isdnguard", sizeof(utype))) {
1377 + write(woof->fd, "START\n", 6);
1379 + ast_pthread_create(&woof->watchdog_thread, NULL, do_watchdog_thread, woof);
1381 + ast_log(LOG_WARNING, "error opening watchdog device %s !\n", woof->device);
1385 + ast_config_destroy(cfg);
1391 +static int unload_module(void)
1393 + struct watchdog_pvt *dogs, *woof;
1396 + pthread_cancel(dogs->watchdog_thread);
1397 + pthread_join(dogs->watchdog_thread, NULL);
1399 + woof = dogs->next;
1407 +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Watchdog Resource",
1408 + .load = load_module,
1409 + .unload = unload_module,
1413 @@ -574,7 +574,7 @@ static int manager_dbget(struct mansessi
1414 astman_append(s, "Event: DBGetResponse\r\n"
1421 family, key, tmp, idText);
1422 @@ -582,11 +582,35 @@ static int manager_dbget(struct mansessi
1426 +static int manager_dbdel(struct mansession *s, const struct message *m)
1428 + const char *family = astman_get_header(m, "Family");
1429 + const char *key = astman_get_header(m, "Key");
1431 + if (!strlen(family)) {
1432 + astman_send_error(s, m, "No family specified");
1435 + if (!strlen(key)) {
1436 + astman_send_error(s, m, "No key specified");
1440 + if (ast_db_del(family, key)) {
1441 + astman_send_error(s, m, "Failed to delete entry");
1443 + astman_send_ack(s, m, "Deleted entry successfully");
1449 int astdb_init(void)
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");
1461 +++ b/configs/esel.conf.sample
1464 +; Configuration file for res_esel
1468 +;host = 192.168.0.1
1470 +;username = manager
1473 +; export the extension snom in context phones to DS/100
1474 +;export => snom@phones,100
1476 +++ b/res/res_esel.c
1479 + * Asterisk -- A telephony toolkit for Linux.
1481 + * Extension State Export Logic (E.S.E.L) (Sorry, i couldnt resist...)
1483 + * Resource to export extension states to other Asterisk servers
1485 + * Copyright (C) 2006, Junghanns.NET GmbH
1487 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1489 + * This program is free software, distributed under the terms of
1490 + * the GNU General Public License
1493 +#include "asterisk.h"
1495 +#include <stdlib.h>
1497 +#include <unistd.h>
1498 +#include <string.h>
1499 +#include <stdlib.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>
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"
1525 +AST_MUTEX_DEFINE_STATIC(listlock);
1527 +typedef struct esel_extension_state {
1528 + char context[AST_MAX_EXTENSION];
1529 + char exten[AST_MAX_EXTENSION];
1531 + char devstate[AST_MAX_EXTENSION];
1532 + struct esel_extension_state *next;
1533 + struct esel_extension_state *prev;
1534 +} esel_extension_state;
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;
1543 +typedef struct esel_queue {
1544 + struct esel_extension_state *head;
1545 + struct esel_extension_state *tail;
1551 +typedef struct esel_pvt {
1553 + char username[80];
1557 + struct sockaddr_in raddr;
1560 + pthread_t esel_thread;
1562 + /* list of extensions to export */
1563 + struct esel_export *extensions;
1566 + struct esel_queue queue;
1568 + struct esel_pvt *next;
1571 +static struct esel_pvt *donkeys = NULL;
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;
1576 + exstate = malloc(sizeof(struct esel_extension_state));
1578 + ast_log(LOG_ERROR, "Unable to malloc!\n");
1581 + memset(exstate,0,sizeof(struct esel_extension_state));
1582 + exstate->next = NULL;
1583 + exstate->prev = NULL;
1585 + ast_mutex_lock(&queue->lock);
1586 + if (queue->count > 100) {
1587 + ast_mutex_unlock(&queue->lock);
1589 + if (option_verbose > 5)
1590 + ast_log(LOG_WARNING, "E.S.E.L Queue too long.\n");
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) {
1598 + queue->head = exstate;
1599 + queue->tail = exstate;
1602 + queue->tail->next = exstate;
1603 + exstate->prev = queue->tail;
1604 + queue->tail = exstate;
1607 + ast_cond_signal(&queue->cond);
1608 + ast_mutex_unlock(&queue->lock);
1612 +static int esel_is_exported(struct esel_export *extensions, struct esel_extension_state *exstate) {
1613 + struct esel_export *export = NULL;
1614 + export = extensions;
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));
1621 + export = export->next;
1626 +static int esel_state2devstate(int state) {
1637 +static void esel_export_to_remote(struct esel_extension_state *exstate, struct esel_pvt *esel) {
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);
1644 + esel->connected = 0;
1646 +// ast_log(LOG_NOTICE, "%s", msg);
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;
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;
1665 + if (exstate->next) {
1666 + queue->head = exstate->next;
1668 + queue->head = NULL;
1669 + queue->tail = NULL;
1673 + ast_log(LOG_ERROR, "I SHOULD NEVER HAPPEN! EXPECT SOME MAJOR KABOOM! DUCK AND COVER!\n");
1675 + ast_mutex_unlock(&queue->lock);
1678 + if (esel_is_exported(esel->extensions, exstate)) {
1679 + esel_export_to_remote(exstate, esel);
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");
1691 + /* try to connect */
1692 + res = connect(esel->sockfd, (struct sockaddr *)&esel->raddr, sizeof(struct sockaddr));
1694 + ast_log(LOG_NOTICE, "error connecting to %s:%d\n", esel->host, esel->port);
1696 + while (strncasecmp(buf, "Asterisk Call Manager:", 21)) {
1697 + if ((numbytes=recv(esel->sockfd, buf, sizeof(buf), 0)) == -1) {
1698 + esel->connected = 0;
1701 + buf[numbytes] = '\0';
1702 + // ast_log(LOG_NOTICE, "read: %s", buf);
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);
1709 + while (strncasecmp(buf, "Response:", 9)) {
1710 + if ((numbytes=recv(esel->sockfd, buf, sizeof(buf), 0)) == -1) {
1713 + buf[numbytes] = '\0';
1714 + // ast_log(LOG_NOTICE, "read: %s", buf);
1717 + if (!strncasecmp(buf, "Response: Success", 17)) {
1718 + esel->connected = 1;
1720 + ast_log(LOG_ERROR, "error login into remote asterisk %s\n", esel->name);
1723 + /* time heals everything... */
1730 +static int esel_state_cb(char *context, char *exten, int state, void *data) {
1731 + struct esel_pvt *esel;
1734 + ast_mutex_lock(&listlock);
1736 + esel_queue_extension_state(&esel->queue, context, exten, state, data);
1737 + esel = esel->next;
1739 + ast_mutex_unlock(&listlock);
1744 +static int load_module(void)
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;
1755 + cfg = ast_config_load("esel.conf");
1757 + cat = ast_category_browse(cfg, NULL);
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");
1765 + if (name && host && username && secret && port) {
1766 + esel = malloc(sizeof(struct esel_pvt));
1768 + ast_log(LOG_ERROR, "unable to malloc!\n");
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));
1777 + esel->port = atoi(port);
1778 + if ((he=ast_gethostbyname(host, &h)) == NULL) {
1779 + ast_log(LOG_ERROR, "unknown host!\n");
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);
1788 + esel->connected = 0;
1790 + ast_mutex_init(&esel->queue.lock);
1791 + ast_cond_init(&esel->queue.cond, NULL);
1794 + /* read exports */
1795 + var = ast_variable_browse(cfg, cat);
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));
1805 + ast_log(LOG_ERROR, "unable to malloc!\n");
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;
1824 + esel->next = donkeys;
1827 + ast_pthread_create(&esel->esel_thread, NULL, do_esel_thread, esel);
1830 + cat = ast_category_browse(cfg, cat);
1832 + ast_config_destroy(cfg);
1834 + ast_extension_state_add(NULL, NULL, esel_state_cb, NULL);
1839 +static int unload_module(void)
1841 + struct esel_pvt *esel, *eseln;
1842 + ast_module_user_hangup_all();
1844 + ast_mutex_lock(&listlock);
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;
1854 + ast_mutex_unlock(&listlock);
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,
1862 --- a/channels/chan_iax2.c
1863 +++ b/channels/chan_iax2.c
1865 * the project provides a web site, mailing lists and IRC
1866 * channels for your use.
1868 + * Hangup cause signalling implementation by
1869 + * Levent Guendogdu <levon@feature-it.com>
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]) {
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
1885 static struct ast_frame *iax2_read(struct ast_channel *c)
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;
1893 --- a/apps/app_zapras.c
1894 +++ b/apps/app_zapras.c
1895 @@ -183,7 +183,7 @@ static void run_ras(struct ast_channel *
1898 /* Throw back into audio mode */
1901 ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
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;
1910 + int dyna_buff = CONF_SIZE;
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;
1917 @@ -1604,7 +1605,7 @@ static int conf_run(struct ast_channel *
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 *
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;
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);
1941 Answer the channel before saying things (SayNumber, SayDigits,
1942 SayCharacters, SayPhonetic).
1946 @@ -6060,6 +6060,9 @@ static int pbx_builtin_saynumber(struct
1950 + if (chan->_state != AST_STATE_UP) {
1953 return ast_say_number(chan, atoi(tmp), "", chan->language, options);
1956 @@ -6067,8 +6070,12 @@ static int pbx_builtin_saydigits(struct
1962 + if (chan->_state != AST_STATE_UP) {
1965 res = ast_say_digit_str(chan, data, "", chan->language);
1970 @@ -6076,8 +6083,12 @@ static int pbx_builtin_saycharacters(str
1976 + if (chan->_state != AST_STATE_UP) {
1979 res = ast_say_character_str(chan, data, "", chan->language);
1984 @@ -6085,8 +6096,12 @@ static int pbx_builtin_sayphonetic(struc
1990 + if (chan->_state != AST_STATE_UP) {
1993 res = ast_say_phonetic_str(chan, data, "", chan->language);
1998 --- a/apps/app_dial.c
1999 +++ b/apps/app_dial.c
2001 * the project provides a web site, mailing lists and IRC
2002 * channels for your use.
2004 + * Copyright (C) 2004, Junghanns.NET GmbH
2006 + * Klaus-Peter Junghanns <kpj@junghanns.net>
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"
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
2025 - strcpy(status, "CHANUNAVAIL");
2026 + ast_copy_string(status, "CHANUNAVAIL", sizeof(status));
2027 if(fulldial == num_dialed) {
2031 + /* See if there is a special message */
2032 + ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
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)) {
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"
2048 static char *app = "Dial";
2050 @@ -1654,23 +1655,25 @@ static int dial_exec_full(struct ast_cha
2051 ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
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);
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;
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
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));
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);
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);
2138 case AST_CONTROL_HOLD:
2139 @@ -659,7 +663,7 @@ static struct ast_channel *wait_for_answ
2140 /* Ignore going off hook and flash */
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");
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 */
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);
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);
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);
2175 @@ -1444,7 +1448,7 @@ static int dial_exec_full(struct ast_cha
2177 if (ast_test_flag(&opts, OPT_MUSICBACK)) {
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);
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;
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);
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);
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);
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");
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 */
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"
2254 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
2256 /*! Global jitterbuffer configuration - by default, jb is disabled */
2257 @@ -703,6 +705,7 @@ static const struct ast_channel_tech zap
2259 .setoption = zt_setoption,
2260 .func_channel_read = zt_func_read,
2261 +/* .devicestate = zt_devicestate, */
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) */)
2269 +static int zt_devicestate(void *data)
2271 + int groupmatch = 0;
2272 + int channelmatch = 0;
2279 + struct zt_pvt *exit, *start, *end;
2280 + ast_mutex_t *lock;
2282 +// ast_log(LOG_NOTICE, "data = %s\n", (char *)data);
2283 + return AST_DEVICE_UNKNOWN;
2285 + /* Assume we're locking the iflock */
2291 + dest = ast_strdupa((char *)data);
2293 + ast_log(LOG_WARNING, "Channel requested with no data\n");
2294 + return AST_DEVICE_INVALID;
2296 + if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
2297 + /* Retrieve the group number */
2298 + char *stringp=NULL;
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;
2305 + groupmatch = 1 << x;
2307 + char *stringp=NULL;
2309 + s = strsep(&stringp, "/");
2311 + if (!strcasecmp(s, "pseudo")) {
2312 + /* Special case for pseudo */
2316 + return AST_DEVICE_INVALID;
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;
2324 + ast_log(LOG_NOTICE, "channelmatch = %d\n", channelmatch);
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;
2334 + res = AST_DEVICE_INVALID; /* start pessimistic */
2337 + ast_mutex_lock(&p->lock);
2338 + if ((groupmatch && ((p->group & groupmatch) != 0)) || (channelmatch && (p->channel == channelmatch))) {
2341 + for(d=0;d<NUM_DCHANS;d++) {
2342 + if (p->pri->dchanavail[d] & DCHAN_UP) {
2343 + res = AST_DEVICE_UNKNOWN;
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;
2351 + if ((p->owner->_state == AST_STATE_RINGING) && (p->outgoing)) {
2352 + res = AST_DEVICE_RINGING;
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;
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);
2365 + ast_mutex_unlock(&p->lock);
2369 + ast_mutex_unlock(lock);
2375 static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
2378 Change the API of ast_sendtext and chan->sendtext to add dest and ispdu
2379 parameters, used by ast_send_message which is also introduced by this patch.
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);
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);
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
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);
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.
2404 +int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu);
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
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);
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
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)
2433 /* Stop if we're a zombie or need a soft hangup */
2434 @@ -2702,7 +2702,7 @@ int ast_sendtext(struct ast_channel *cha
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);
2443 @@ -2881,7 +2881,7 @@ int ast_write(struct ast_channel *chan,
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);
2450 case AST_FRAME_HTML:
2451 res = (chan->tech->send_html == NULL) ? 0 :
2452 @@ -4908,6 +4908,25 @@ void ast_channel_stop_silence_generator(
2456 +int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu) {
2457 + struct ast_channel *chan = NULL;
2461 + chan = ast_request(type, AST_FORMAT_SLINEAR, data, &status);
2464 + ast_set_callerid(chan, from, from, from);
2466 + res = ast_sendtext(chan, to, message, ispdu);
2467 + /* XXX what about message CDRs ??? XXX */
2475 /*! \ brief Convert channel reloadreason (ENUM) to text string for manager event */
2476 const char *channelreloadreason2txt(enum channelreloadreason reason)
2478 --- a/apps/app_sendtext.c
2479 +++ b/apps/app_sendtext.c
2480 @@ -103,7 +103,7 @@ static int sendtext_exec(struct ast_chan
2483 ast_channel_unlock(chan);
2484 - res = ast_sendtext(chan, args.text);
2485 + res = ast_sendtext(chan, NULL, args.text, 0);
2488 pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status);
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;
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
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)
2518 struct agent_pvt *p = ast->tech_pvt;
2520 ast_mutex_lock(&p->lock);
2522 - res = ast_sendtext(p->chan, text);
2523 + res = ast_sendtext(p->chan, dest, text, ispdu);
2524 ast_mutex_unlock(&p->lock);
2527 --- a/channels/chan_alsa.c
2528 +++ b/channels/chan_alsa.c
2529 @@ -186,7 +186,7 @@ static int nosound = 0;
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
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)
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);
2557 /* PBX interface structure for channel registration */
2558 @@ -390,7 +390,7 @@ static int local_digit_end(struct ast_ch
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)
2565 struct local_pvt *p = ast->tech_pvt;
2567 --- a/channels/chan_oss.c
2568 +++ b/channels/chan_oss.c
2569 @@ -405,7 +405,7 @@ static struct ast_channel *oss_request(c
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
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)
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);
2598 @@ -640,7 +640,7 @@ static int phone_write_buf(struct phone_
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)
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)
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)
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);
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)
2646 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
2647 --- a/main/manager.c
2648 +++ b/main/manager.c
2650 * the project provides a web site, mailing lists and IRC
2651 * channels for your use.
2653 + * Copyright (C) 2003-2004, Junghanns.NET Gmbh
2654 + * Klaus-Peter Junghanns <kpj@junghanns.net>
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
2663 +static char mandescr_message[] =
2664 +"Description: Send a message\n"
2666 +" Channel: The destination channel(e.g. SIP/phone1)\n"
2668 +" Message: The message to send\n";
2670 +static int action_message(struct mansession *s, const struct message *m)
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");
2677 + char *tech, *data;
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");
2683 + ast_copy_string(tmp, name, sizeof(tmp));
2685 + data = strchr(tmp, '/');
2687 + astman_send_error(s, m, "Invalid channel\n");
2692 + if (ast_strlen_zero(pdu)) {
2693 + res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)message, 0);
2695 + res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)pdu, 1);
2699 + astman_send_error(s, m, "Error sending message");
2702 + astman_send_ack(s, m, "Message sent");
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 {
2724 + char message[256];
2727 /* If extension/context/priority */
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
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);
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);
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");
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);
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");
2779 + remove_from_queue(o, "Completed");
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];
2793 enum AST_MONITORING_STATE state;
2794 @@ -46,7 +48,7 @@ struct ast_channel_monitor {
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 );
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
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)
2814 @@ -153,6 +153,11 @@ int ast_monitor_start( struct ast_channe
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));
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)) {
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));
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));
2845 + ast_log(LOG_NOTICE,"monitor executing %s\n",tmp);
2846 + result = ast_safe_system(tmp);
2848 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
2851 @@ -452,7 +464,7 @@ static int start_monitor_exec(struct ast
2855 - res = ast_monitor_start(chan, format, fname_base, 1);
2856 + res = ast_monitor_start(chan, format, fname_base, NULL, NULL, 1);
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");
2868 if (ast_strlen_zero(name)) {
2869 @@ -515,7 +529,7 @@ static int start_monitor_action(struct m
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
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 );
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 );
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, '.')))
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);
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
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);
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
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);
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
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];
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
2943 -static void do_state_change(const char *device)
2944 +static void do_state_change(const char *device, char *cid_num, char *cid_name)
2947 struct devstate_cb *devcb;
2948 @@ -288,13 +290,13 @@ static void do_state_change(const char *
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);
2956 - ast_hint_state_changed(device);
2957 + ast_hint_state_changed(device, cid_num, cid_name);
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)
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);
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);
2977 + if (cid_name && (!ast_strlen_zero(cid_name))) {
2978 + strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
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
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)
2991 + char *buf2 = NULL;
2992 + char *buf3 = NULL;
2993 buf = ast_strdupa(dev);
2994 - return __ast_device_state_changed_literal(buf);
2996 + buf2 = ast_strdupa(cid_num);
2998 + buf3 = ast_strdupa(cid_name);
2999 + return __ast_device_state_changed_literal(buf, buf2, buf3);
3002 /*! \brief Accept change notification, add it to change queue */
3003 @@ -343,7 +357,7 @@ int ast_device_state_changed(const char
3005 vsnprintf(buf, sizeof(buf), fmt, ap);
3007 - return __ast_device_state_changed_literal(buf);
3008 + return __ast_device_state_changed_literal(buf, NULL, NULL);
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
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);
3019 AST_LIST_LOCK(&state_changes);
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);
3027 +extern ast_mutex_t uniquelock;
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);
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);
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
3042 AST_LIST_UNLOCK(&channels);
3044 - ast_device_state_changed_literal(name);
3045 + ast_device_state_changed_literal(name, NULL, NULL);
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);
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)
3056 int oldstate = chan->_state;
3058 @@ -3949,7 +3949,7 @@ int ast_setstate(struct ast_channel *cha
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,
3067 @@ -3966,6 +3966,11 @@ int ast_setstate(struct ast_channel *cha
3071 +int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
3073 + return ast_setstate_and_cid(chan, state, NULL, NULL);
3076 /*! \brief Find bridged channel */
3077 struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
3079 --- a/include/asterisk/pbx.h
3080 +++ b/include/asterisk/pbx.h
3081 @@ -63,7 +63,7 @@ struct ast_ignorepat;
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);
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
3092 int ast_func_write(struct ast_channel *chan, char *function, const char *value);
3094 -void ast_hint_state_changed(const char *device);
3095 +void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name);
3097 #if defined(__cplusplus) || defined(c_plusplus)
3101 @@ -2011,7 +2011,7 @@ int ast_extension_state(struct ast_chann
3102 return ast_extension_state2(e); /* Check all devices in the hint */
3105 -void ast_hint_state_changed(const char *device)
3106 +void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
3108 struct ast_hint *hint;
3110 @@ -2042,11 +2042,11 @@ void ast_hint_state_changed(const char *
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);
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);
3122 hint->laststate = state; /* record we saw the change */
3124 @@ -2241,7 +2241,7 @@ static int ast_remove_hint(struct ast_ex
3125 /* Notify with -1 and remove all callbacks */
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);
3132 hint->callbacks = NULL;
3133 @@ -4008,7 +4008,7 @@ void ast_merge_contexts_and_delete(struc
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);
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);
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)
3160 struct sip_pvt *p = data;
3162 --- a/apps/app_queue.c
3163 +++ b/apps/app_queue.c
3164 @@ -690,7 +690,7 @@ static void *device_state_thread(void *d
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)
3171 struct statechange *sc;
3173 --- a/include/asterisk/manager.h
3174 +++ b/include/asterisk/manager.h
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 */
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" },
3193 @@ -2538,10 +2539,12 @@ int ast_manager_unregister(char *action)
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)
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);
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[])
3215 + if ((argc != 3) && (argc != 4) && (argc != 5))
3216 return RESULT_SHOWUSAGE;
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");
3222 snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
3223 - ast_device_state_changed_literal(devName);
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]);
3231 + ast_device_state_changed_literal(devName, NULL, NULL);
3233 return RESULT_SUCCESS;
3236 @@ -93,7 +101,7 @@ static int devstate_exec(struct ast_chan
3239 snprintf(devName, sizeof(devName), "DS/%s", device);
3240 - ast_device_state_changed_literal(devName);
3241 + ast_device_state_changed_literal(devName, NULL, NULL);
3243 ast_module_user_remove(u);
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");
3252 char idText[256] = "";
3254 @@ -166,7 +176,7 @@ static int action_devstate(struct manses
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);
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];
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 {
3276 static struct esel_pvt *donkeys = NULL;
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;
3282 exstate = malloc(sizeof(struct esel_extension_state));
3283 @@ -115,6 +117,8 @@ static int esel_queue_extension_state(st
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;
3292 @@ -161,7 +165,7 @@ static void esel_export_to_remote(struct
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);
3300 esel->connected = 0;
3301 @@ -250,13 +254,13 @@ static void *do_esel_thread(void *data)
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;
3310 ast_mutex_lock(&listlock);
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);
3316 ast_mutex_unlock(&listlock);
3317 Use Asterisk's process ID when building the unique ID.
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;
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));
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));
3334 Add or convert channel operations so they can use the unique ID.
3336 --- a/include/asterisk/channel.h
3337 +++ b/include/asterisk/channel.h
3338 @@ -659,6 +659,18 @@ void ast_channel_free(struct ast_channe
3340 struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
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.
3352 +struct ast_channel *ast_request_with_uniqueid(const char *type, int format, void *data, int *status, char *uniqueid);
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.
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);
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);
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);
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
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)
3387 const char *msg = prev ? "deadlock" : "initial deadlock";
3389 @@ -1063,7 +1063,10 @@ static struct ast_channel *channel_find_
3390 * XXX Need a better explanation for this ...
3393 - if (name) { /* want match by name */
3395 + if (!strcasecmp(c->uniqueid, uniqueid))
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)
3405 - return channel_find_locked(prev, NULL, 0, NULL, NULL);
3406 + return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
3409 /*! \brief Get channel by name and lock it */
3410 struct ast_channel *ast_get_channel_by_name_locked(const char *name)
3412 - return channel_find_locked(NULL, name, 0, NULL, NULL);
3413 + return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
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)
3419 - return channel_find_locked(NULL, name, namelen, NULL, NULL);
3420 + return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
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,
3427 - return channel_find_locked(chan, name, namelen, NULL, NULL);
3428 + return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
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)
3434 - return channel_find_locked(NULL, NULL, 0, context, exten);
3435 + return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
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)
3442 - return channel_find_locked(chan, NULL, 0, context, exten);
3443 + return channel_find_locked(chan, NULL, 0, context, exten, NULL);
3446 +struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
3448 + return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
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);
3457 - sched_context_destroy(chan->sched);
3458 + if (chan->sched) {
3459 + sched_context_destroy(chan->sched);
3460 + chan->sched = NULL;
3463 ast_copy_string(name, chan->name, sizeof(name));
3465 @@ -3106,7 +3116,7 @@ char *ast_channel_reason2str(int reason)
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)
3474 @@ -3118,7 +3128,7 @@ struct ast_channel *__ast_request_and_di
3476 outstate = &dummy_outstate; /* make outstate always a valid pointer */
3478 - chan = ast_request(type, format, data, &cause);
3479 + chan = ast_request_with_uniqueid(type, format, data, &cause, uniqueid);
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);
3486 ast_set_callerid(chan, cid_num, cid_name, cid_num);
3488 + chan->cid.cid_pres = callingpres;
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
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)
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);
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)
3506 struct chanlist *chan;
3507 struct ast_channel *c;
3508 @@ -3285,6 +3295,11 @@ struct ast_channel *ast_request(const ch
3512 +struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
3514 + return ast_request_with_uniqueid(type, format, data, cause, NULL);
3517 int ast_call(struct ast_channel *chan, char *addr, int timeout)
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);
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);
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);
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);
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);
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);
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);
3558 * \brief Evaluate a condition
3562 @@ -4985,7 +4985,7 @@ static int ast_pbx_outgoing_cdr_failed(v
3563 return 0; /* success */
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)
3569 struct ast_channel *chan;
3570 struct async_stat *as;
3571 @@ -4995,7 +4995,7 @@ int ast_pbx_outgoing_exten(const char *t
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);
3580 @@ -5080,7 +5080,7 @@ int ast_pbx_outgoing_exten(const char *t
3582 goto outgoing_exten_cleanup;
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);
3589 @@ -5120,6 +5120,10 @@ outgoing_exten_cleanup:
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)
3595 + return ast_pbx_outgoing_exten2(type, format, data, timeout, context, exten, priority, reason, sync, 0, cid_num, cid_name, vars, account, channel, NULL);
3600 @@ -5144,7 +5148,7 @@ static void *ast_pbx_run_app(void *data)
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)
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;
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);
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);
3620 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */
3622 @@ -5247,7 +5251,7 @@ int ast_pbx_outgoing_app(const char *typ
3624 goto outgoing_app_cleanup;
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);
3631 @@ -5287,6 +5291,10 @@ outgoing_app_cleanup:
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)
3637 + return ast_pbx_outgoing_app2(type, format, data, timeout, app, appdata, reason, sync, 0, cid_num, cid_name, vars, account, locked_channel, NULL);
3639 void __ast_context_destroy(struct ast_context *con, const char *registrar)
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);
3647 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
3648 + manager_event(EVENT_FLAG_CALL, "MonitorStopped",
3650 + "Uniqueid: %s\r\n"
3652 + ,chan->name, chan->uniqueid, result);
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");
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");
3672 + if (!ast_strlen_zero(uniqueid)) {
3673 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
3675 + astman_send_error(s, m, "No such uniqueid");
3678 - c = ast_get_channel_by_name_locked(name);
3682 + c = ast_get_channel_by_name_locked(name);
3684 astman_send_error(s, m, "No such channel");
3689 if (ast_strlen_zero(fname)) {
3690 @@ -555,16 +570,30 @@ static int stop_monitor_action(struct ma
3692 struct ast_channel *c = NULL;
3693 const char *name = astman_get_header(m, "Channel");
3694 + const char *uniqueid = astman_get_header(m, "Uniqueid");
3696 if (ast_strlen_zero(name)) {
3697 astman_send_error(s, m, "No channel specified");
3700 - c = ast_get_channel_by_name_locked(name);
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");
3707 + if (!ast_strlen_zero(uniqueid)) {
3708 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
3710 + astman_send_error(s, m, "No such uniqueid");
3714 + c = ast_get_channel_by_name_locked(name);
3716 + astman_send_error(s, m, "No such channel");
3721 res = ast_monitor_stop(c, 1);
3722 ast_channel_unlock(c);
3724 --- a/apps/app_chanspy.c
3725 +++ b/apps/app_chanspy.c
3726 @@ -55,6 +55,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
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 =
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"
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"
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
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)
3769 struct ast_channel *this;
3771 @@ -413,6 +435,8 @@ static struct ast_channel *next_channel(
3772 this = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
3774 this = ast_walk_channel_by_exten_locked(last, exten, context);
3775 + else if (uniqueid)
3776 + this = ast_get_channel_by_uniqueid_locked(uniqueid);
3778 this = ast_channel_walk_locked(last);
3780 @@ -427,7 +451,7 @@ static struct ast_channel *next_channel(
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)
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
3791 peer = prev = next = NULL;
3793 - for (peer = next_channel(peer, spec, exten, context);
3794 + for (peer = next_channel(peer, spec, exten, context, NULL);
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) {
3799 int igrp = !mygroup;
3801 @@ -625,7 +649,7 @@ static int chanspy_exec(struct ast_chann
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);
3810 @@ -710,7 +734,92 @@ static int extenspy_exec(struct ast_chan
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);
3820 + if (oldwf && ast_set_write_format(chan, oldwf) < 0)
3821 + ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
3823 + ast_module_user_remove(u);
3828 +static int chanspychan_exec(struct ast_channel *chan, void *data)
3830 + struct ast_module_user *u;
3831 + char *options = NULL;
3832 + char *uniqueid = NULL;
3834 + char *mygroup = NULL;
3835 + char *recbase = NULL;
3837 + struct ast_flags flags;
3840 + int volfactor = 0;
3843 + data = ast_strdupa(data);
3845 + u = ast_module_user_add(chan);
3847 + if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
3848 + uniqueid = argv[0];
3850 + options = argv[1];
3852 + if (ast_strlen_zero(uniqueid)) {
3853 + ast_log(LOG_ERROR, "no uniqueid specified.\n");
3854 + ast_module_user_remove(u);
3860 + char *opts[OPT_ARG_ARRAY_SIZE];
3862 + ast_app_parse_options(spy_opts, &flags, opts, options);
3863 + if (ast_test_flag(&flags, OPTION_GROUP))
3864 + mygroup = opts[OPT_ARG_GROUP];
3866 + if (ast_test_flag(&flags, OPTION_RECORD) &&
3867 + !(recbase = opts[OPT_ARG_RECORD]))
3868 + recbase = "chanspy";
3870 + if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
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");
3879 + if (ast_test_flag(&flags, OPTION_PRIVATE))
3880 + ast_set_flag(&flags, OPTION_WHISPER);
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);
3891 + char filename[512];
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);
3900 + res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, NULL, uniqueid);
3904 @@ -723,14 +832,15 @@ static int extenspy_exec(struct ast_chan
3909 static int unload_module(void)
3913 res |= ast_unregister_application(app_chan);
3914 + res |= ast_unregister_application(app_chan2);
3915 res |= ast_unregister_application(app_ext);
3917 - ast_module_user_hangup_all();
3921 @@ -741,6 +851,7 @@ static int load_module(void)
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);
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];
3936 + char uniqueid[64];
3937 struct ast_variable *vars;
3940 @@ -1415,11 +1417,20 @@ static int action_hangup(struct mansessi
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");
3948 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
3949 + astman_send_error(s, m, "No channel or uniqueid specified");
3952 - c = ast_get_channel_by_name_locked(name);
3954 + if (!ast_strlen_zero(uniqueid)) {
3955 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
3957 + if (!ast_strlen_zero(name))
3958 + c = ast_get_channel_by_name_locked(name);
3962 astman_send_error(s, m, "No such channel");
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;
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");
3984 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
3985 @@ -1685,7 +1702,11 @@ static int action_redirect(struct manses
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);
3993 + chan = ast_get_channel_by_name_locked(name);
3997 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
3998 @@ -1707,9 +1728,9 @@ static int action_redirect(struct manses
4000 res = ast_async_goto(chan, context, exten, pi);
4002 - if (!ast_strlen_zero(name2)) {
4003 + if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
4005 - res = ast_async_goto(chan2, context, exten, pi);
4006 + res = ast_async_goto(chan2, context2, exten2, pi2);
4010 @@ -1788,15 +1809,15 @@ static void *fast_originate(void *data)
4011 char requested_channel[AST_CHANNEL_NAME];
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);
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);
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);
4037 char *l = NULL, *n = NULL;
4038 @@ -1865,6 +1887,9 @@ static int action_originate(struct manse
4044 + char idText[256] = "";
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");
4052 + if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
4053 + astman_send_error(s, m, "Invalid CallingPres\n");
4056 ast_copy_string(tmp, name, sizeof(tmp));
4058 data = strchr(tmp, '/');
4059 @@ -1901,6 +1930,7 @@ static int action_originate(struct manse
4060 if (ast_strlen_zero(l))
4063 + uniqueid = ast_alloc_uniqueid();
4064 if (ast_true(async)) {
4065 struct fast_originate_helper *fast = ast_calloc(1, sizeof(*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));
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);
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);
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);
4089 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
4094 - astman_send_ack(s, m, "Originate successfully queued");
4097 + if (id && !ast_strlen_zero(id)) {
4098 + snprintf(idText,256,"ActionID: %s\r\n",id);
4100 + ast_cli(s->fd, "Response: Success\r\n"
4102 + "Message: Originate successfully queued\r\n"
4103 + "Uniqueid: %s\r\n"
4105 + idText, uniqueid);
4107 astman_send_error(s, m, "Originate failed");
4112 --- a/include/asterisk/channel.h
4113 +++ b/include/asterisk/channel.h
4116 #include "asterisk/abstract_jb.h"
4118 +/* Max length of the uniqueid */
4119 +#define AST_MAX_UNIQUEID 64
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);
4128 +char *ast_alloc_uniqueid(void);
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)",
4139 +/*! \brief Create a uniqueid */
4140 +char *ast_alloc_uniqueid(void) {
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));
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, ...)
4151 --- a/include/asterisk/features.h
4152 +++ b/include/asterisk/features.h
4153 @@ -47,6 +47,8 @@ struct ast_call_feature {
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);
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
4165 * the project provides a web site, mailing lists and IRC
4166 * channels for your use.
4168 + * Copyright (C) 2004, Junghanns.NET GmbH
4170 + * Klaus-Peter Junghanns <kpj@junghanns.net>
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"
4179 +static char *autoanswerlogin = "AutoanswerLogin";
4181 +static char *synopsis3 = "Log in for autoanswer";
4183 +static char *descrip3 = "AutoanswerLogin([context]|exten):"
4184 +"Used to login to the autoanswer application for an extension.\n";
4186 +static char *autoanswer = "Autoanswer";
4188 +static char *synopsis4 = "Autoanswer a call";
4190 +static char *descrip4 = "Autoanswer([context]|exten):"
4191 +"Used to autoanswer a call for an extension.\n";
4193 static struct ast_app *monitor_app = NULL;
4194 static int monitor_ok = 1;
4196 @@ -146,6 +164,23 @@ struct parkeduser {
4197 struct parkeduser *next;
4200 +/* auto answer user */
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];
4209 + struct aauser *next;
4213 +static struct aauser *aalot;
4214 +AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
4215 +static pthread_t autoanswer_thread;
4217 static struct parkeduser *parkinglot;
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
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
4235 if (peer && adsipark && ast_adsi_available(peer)) {
4236 @@ -1628,11 +1665,13 @@ static void post_manager_event(const cha
4240 - "CallerIDName: %s\r\n\r\n",
4241 + "CallerIDName: %s\r\n"
4242 + "Uniqueid: %s\r\n\r\n",
4245 S_OR(chan->cid.cid_num, "<unknown>"),
4246 - S_OR(chan->cid.cid_name, "<unknown>")
4247 + S_OR(chan->cid.cid_name, "<unknown>"),
4252 @@ -1887,10 +1926,12 @@ static int park_exec(struct ast_channel
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
4267 @@ -2044,15 +2085,10 @@ static struct ast_cli_entry cli_show_fea
4268 handle_showfeatures, NULL,
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";
4279 - { { "show", "parkedcalls", NULL },
4280 - handle_parkedcalls, "Lists parked calls",
4281 - showparked_help },
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
4289 "CallerIDName: %s\r\n"
4290 + "Unqiueid: %s\r\n\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,
4301 @@ -2156,6 +2193,427 @@ static int manager_park(struct mansessio
4305 +static int handle_autoanswer(int fd, int argc, char *argv[])
4307 + struct aauser *cur;
4309 + ast_cli(fd, "%25s %10s %15s \n", "Channel"
4310 + , "Extension", "Context");
4312 + ast_mutex_lock(&autoanswer_lock);
4316 + ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
4321 + ast_mutex_unlock(&autoanswer_lock);
4323 + return RESULT_SUCCESS;
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 },
4331 + { { "show", "parkedcalls", NULL },
4332 + handle_parkedcalls, "Lists parked calls",
4333 + showparked_help },
4335 + { { "show", "autoanswer", NULL },
4336 + handle_autoanswer, "Lists autoanswer users",
4337 + showautoanswer_help },
4339 +int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
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);
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);
4362 + ast_autoanswer_login(chan, data);
4364 + ast_log(LOG_WARNING, "Unable to create aa channel\n");
4370 +static int autoanswer_login_exec(struct ast_channel *chan, void *data)
4373 + struct ast_module_user *u;
4375 + u = ast_module_user_add(chan);
4377 + ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
4380 + res = ast_masq_autoanswer_login(chan, data);
4381 + ast_module_user_remove(u);
4385 +int ast_autoanswer_login(struct ast_channel *chan, void *data)
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;
4394 + s = ast_strdupa((void *) data);
4396 + aacontext = strsep(&stringp, "|");
4397 + aaexten = strsep(&stringp, "|");
4399 + aaexten = aacontext;
4403 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
4407 + aacontext = "default";
4411 + ast_mutex_lock(&autoanswer_lock);
4414 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
4416 + pl->next = pu->next;
4424 + ast_mutex_unlock(&autoanswer_lock);
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",
4429 + "Uniqueid: %s\r\n"
4432 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
4433 + ast_hangup(pu->chan);
4436 + pu = malloc(sizeof(struct aauser));
4438 + memset(pu, 0, sizeof(pu));
4439 + ast_mutex_lock(&autoanswer_lock);
4440 + chan->appl = "Autoanswer";
4441 + chan->data = NULL;
4444 + if (chan->_state != AST_STATE_UP) {
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);
4455 + con = ast_context_find(aacontext);
4457 + con = ast_context_create(NULL,aacontext, registrar);
4459 + ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
4463 + snprintf(exten, sizeof(exten), "%s", aaexten);
4464 + ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
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",
4474 + "Uniqueid: %s\r\n"
4477 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
4481 + ast_log(LOG_WARNING, "Out of memory\n");
4487 +static void autoanswer_reregister_extensions(void)
4489 + struct aauser *cur;
4490 + struct ast_context *con;
4491 + char exten[AST_MAX_EXTENSION];
4492 + char args[AST_MAX_EXTENSION];
4494 + ast_mutex_lock(&autoanswer_lock);
4498 + con = ast_context_find(cur->context);
4500 + con = ast_context_create(NULL,cur->context, registrar);
4502 + ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", cur->context);
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);
4513 + ast_mutex_unlock(&autoanswer_lock);
4515 +static void *do_autoanswer_thread(void *ignore)
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;
4524 + fd_set rfds, efds;
4525 + fd_set nrfds, nefds;
4531 + ast_mutex_lock(&autoanswer_lock);
4534 + gettimeofday(&tv, NULL);
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);
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",
4554 + "Uniqueid: %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);
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");
4565 + ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
4567 + /* And take them out of the parking lot */
4569 + pl->next = pu->next;
4577 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
4579 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
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];
4593 + /* Keep track of our longest wait */
4594 + if ((tms < ms) || (ms < 0))
4600 + ast_mutex_unlock(&autoanswer_lock);
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();
4609 + return NULL; /* Never reached */
4612 +static int autoanswer_exec(struct ast_channel *chan, void *data)
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;
4624 + ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
4627 + s = ast_strdupa((void *) data);
4629 + aacontext = strsep(&stringp, "|");
4630 + aaexten = strsep(&stringp, "|");
4632 + aaexten = aacontext;
4636 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
4640 + aacontext = "default";
4644 + u = ast_module_user_add(chan);
4645 + ast_mutex_lock(&autoanswer_lock);
4648 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
4650 + pl->next = pu->next;
4658 + ast_mutex_unlock(&autoanswer_lock);
4664 + /* JK02: it helps to answer the channel if not already up */
4665 + if (chan->_state != AST_STATE_UP) {
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");
4682 + res = ast_channel_make_compatible(chan, peer);
4684 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
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",
4694 + "Uniqueid: %s\r\n"
4695 + "Channel2: %s\r\n"
4696 + "Uniqueid2: %s\r\n"
4699 + ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
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);
4711 + if (option_verbose > 2)
4712 + ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
4714 + snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
4715 + ast_autoanswer_login(peer, datastring);
4718 + if (option_verbose > 2)
4719 + ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
4722 + ast_module_user_remove(u);
4727 int ast_pickup_call(struct ast_channel *chan)
4729 @@ -2419,6 +2877,7 @@ static int load_config(void)
4731 static int reload(void)
4733 + autoanswer_reregister_extensions();
4734 return load_config();
4737 @@ -2442,6 +2901,12 @@ static int load_module(void)
4738 "Park a channel", mandescr_park);
4741 + ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
4743 + res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
4745 + res |= ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
4747 res |= ast_devstate_prov_add("Park", metermaidstate);
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);
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
4763 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
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);
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"
4782 #define DEFAULT_PARK_TIME 45000
4783 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
4784 @@ -80,6 +81,7 @@ enum {
4787 static char *parkedcall = "ParkedCall";
4788 +static char *holdedcall = "HoldedCall";
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;
4796 +struct holdeduser {
4797 + struct ast_channel *chan;
4798 + struct timeval start;
4802 + /* Where to go if our parking time expires */
4803 + char context[AST_MAX_EXTENSION];
4804 + char exten[AST_MAX_EXTENSION];
4807 + char uniqueid[AST_MAX_UNIQUEID];
4808 + char uniqueidpeer[AST_MAX_UNIQUEID];
4809 + struct holdeduser *next;
4812 /* auto answer user */
4814 struct ast_channel *chan;
4815 @@ -183,10 +201,16 @@ static pthread_t autoanswer_thread;
4817 static struct parkeduser *parkinglot;
4819 +static struct holdeduser *holdlist;
4821 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
4823 +AST_MUTEX_DEFINE_STATIC(holding_lock);
4825 static pthread_t parking_thread;
4827 +static pthread_t holding_thread;
4829 char *ast_parking_ext(void)
4832 @@ -2011,6 +2035,282 @@ static int park_exec(struct ast_channel
4836 +int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
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));
4843 + memset(pu, 0, sizeof(pu));
4844 + ast_mutex_lock(&holding_lock);
4845 + chan->appl = "Holded Call";
4846 + chan->data = NULL;
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;
4856 + ast_mutex_unlock(&holding_lock);
4857 + /* Wake up the (presumably select()ing) thread */
4858 + pthread_kill(holding_thread, SIGURG);
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);
4868 + ast_log(LOG_WARNING, "Out of memory\n");
4874 +int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
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);
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);
4897 + ast_hold_call(chan, peer);
4900 + ast_log(LOG_WARNING, "Unable to create holded channel\n");
4906 +int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
4908 + int res=-1, dres=-1;
4909 + struct ast_channel *peer=NULL;
4910 + struct ast_bridge_config config;
4912 + peer = ast_get_holded_call(uniqueid);
4914 + /* JK02: it helps to answer the channel if not already up */
4915 + if (chan->_state != AST_STATE_UP) {
4920 + ast_mutex_unlock(&peer->lock);
4921 + ast_moh_stop(peer);
4922 + res = ast_channel_make_compatible(chan, peer);
4924 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
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);
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);
4942 + /* Simulate the PBX hanging up */
4943 + if (res != AST_PBX_NO_HANGUP_PEER)
4947 + /* XXX Play a message XXX */
4948 + dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
4950 + dres = ast_waitstream(chan, "");
4952 + ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
4959 +int ast_retrieve_call_to_death(char *uniqueid)
4962 + struct ast_channel *peer=NULL;
4964 + peer = ast_get_holded_call(uniqueid);
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);
4973 + ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
4978 +struct ast_channel *ast_get_holded_call(char *uniqueid)
4981 + struct ast_channel *peer=NULL;
4982 + struct holdeduser *pu, *pl=NULL;
4984 + ast_mutex_lock(&holding_lock);
4987 + if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
4989 + pl->next = pu->next;
4991 + holdlist = pu->next;
4997 + ast_mutex_unlock(&holding_lock);
4999 + peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
5003 + if (option_verbose > 2)
5004 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
5005 + ast_moh_stop(peer);
5008 + if (option_verbose > 2)
5009 + ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
5013 + ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
5018 +/* this is our autmagically service thread that keeps channels onhold happy */
5019 +static void *do_holding_thread(void *ignore)
5022 + struct holdeduser *pu, *pl, *pt = NULL;
5023 + struct timeval tv;
5024 + struct ast_frame *f;
5026 + fd_set rfds, efds;
5027 + fd_set nrfds, nefds;
5033 + ast_mutex_lock(&holding_lock);
5036 + gettimeofday(&tv, NULL);
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);
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 */
5059 + pl->next = pu->next;
5061 + holdlist = pu->next;
5067 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
5069 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
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];
5083 + /* Keep track of our longest wait */
5084 + if ((tms < ms) || (ms < 0))
5090 + ast_mutex_unlock(&holding_lock);
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();
5099 + return NULL; /* Never reached */
5102 +static int retrieve_call_exec(struct ast_channel *chan, void *data) {
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);
5112 static int handle_showfeatures(int fd, int argc, char *argv[])
5115 @@ -2892,6 +3192,7 @@ static int load_module(void)
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);
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);
5127 + res |= ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
5128 ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
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);
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 */
5148 int nativeformats; /*!< Kinds of data this channel can natively handle */
5151 @@ -5132,7 +5132,7 @@ struct app_tmp {
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)
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
5164 struct ast_app *pbx_findapp(const char *app);
5166 +void *ast_pbx_run_app(void *data);
5169 * \brief Execute an application
5171 --- a/channels/chan_zap.c
5172 +++ b/channels/chan_zap.c
5174 * the project provides a web site, mailing lists and IRC
5175 * channels for your use.
5177 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
5178 + * Klaus-Peter Junghanns <kpj@junghanns.net>
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)
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 */
5193 @@ -218,8 +222,6 @@ static struct ast_channel inuse;
5194 #ifdef PRI_GETSET_TIMERS
5195 static int pritimers[PRI_MAX_TIMERS];
5197 -static int pridebugfd = -1;
5198 -static char pridebugfilename[1024] = "";
5201 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
5202 @@ -237,10 +239,6 @@ AST_MUTEX_DEFINE_STATIC(iflock);
5204 static int ifcount = 0;
5207 -AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
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(
5215 static int zt_sendtext(struct ast_channel *c, const char *text);
5218 /*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
5219 static inline int zt_get_event(int fd)
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)
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;
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 */
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;
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 */
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 */
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 {
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;
5307 + int tei; /* channel in use by this tei */
5308 + q931_call *holdedcall;
5312 @@ -615,11 +647,14 @@ static struct zt_chan_conf zt_chan_conf_
5316 + .nocid = "No CID available",
5317 + .withheldcid = "CID withheld",
5318 .internationalprefix = "",
5319 .nationalprefix = "",
5321 .privateprefix = "",
5322 .unknownprefix = "",
5325 .resetinterval = 3600
5327 @@ -631,6 +666,8 @@ static struct zt_chan_conf zt_chan_conf_
5328 .mohinterpret = "default",
5330 .transfertobusy = 1,
5331 + .priindication_oob = 0,
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);
5343 static const struct ast_channel_tech zap_tech = {
5345 @@ -717,6 +756,13 @@ static const struct ast_channel_tech zap
5346 struct zt_pvt *round_robin[32];
5352 + struct ast_channel *chan;
5356 static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
5359 @@ -1525,12 +1571,16 @@ static void zt_enable_ec(struct zt_pvt *
5363 + if (p->faxhandled) {
5364 + ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
5368 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
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");
5376 if (p->echocancel) {
5377 @@ -1557,7 +1607,7 @@ static void zt_train_ec(struct zt_pvt *p
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);
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);
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);
5394 + set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
5399 if (p->outsigmod > -1)
5400 @@ -2149,6 +2204,7 @@ static int zt_call(struct ast_channel *a
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);
5407 ast_log(LOG_DEBUG, "not yet implemented\n");
5408 @@ -2169,6 +2225,12 @@ static int zt_call(struct ast_channel *a
5410 int redirect_reason;
5412 + if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
5413 + // pass NO audio when ringing an isdn phone
5415 + // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
5418 c = strchr(dest, '/');
5421 @@ -2191,6 +2253,7 @@ static int zt_call(struct ast_channel *a
5422 ast_mutex_unlock(&p->lock);
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
5431 ast_mutex_unlock(&p->lock);
5434 + // ast_log(LOG_NOTICE, "call %d\n", p->call);
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,
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);
5447 @@ -2507,8 +2572,10 @@ static int pri_find_dchan(struct zt_pri
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]);
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
5463 +static int zt_setlaw(int zfd, int law)
5466 + res = ioctl(zfd, ZT_SETLAW, &law);
5473 static int zt_hangup(struct ast_channel *ast)
5476 @@ -2565,8 +2642,7 @@ static int zt_hangup(struct ast_channel
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;
5484 /* Real channel, do some fixup */
5485 p->subs[index].owner = NULL;
5486 @@ -2668,6 +2744,7 @@ static int zt_hangup(struct ast_channel
5489 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
5490 + int outgoing = p->outgoing;
5493 p->distinctivering = 0;
5494 @@ -2710,7 +2787,7 @@ static int zt_hangup(struct ast_channel
5495 pri_call_set_useruser(p->call, useruser);
5498 - pri_hangup(p->pri->pri, p->call, -1);
5499 + pri_hangup(p->pri->pri, p->call, -1, -1);
5502 p->bearer->call = NULL;
5503 @@ -2730,7 +2807,28 @@ static int zt_hangup(struct ast_channel
5505 icause = atoi(cause);
5507 - pri_hangup(p->pri->pri, p->call, icause);
5509 + pri_hangup(p->pri->pri, p->call, icause, -1);
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)) {
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 */
5521 + if (p->pri->nodetype == BRI_NETWORK_PTMP) {
5522 + if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
5532 ast_log(LOG_WARNING, "pri_disconnect failed\n");
5533 @@ -2914,10 +3012,14 @@ static int zt_answer(struct ast_channel
5535 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
5537 + /* stop ignoring inband dtmf */
5538 + enable_dtmf_detect(p);
5540 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5543 + /* the audio path is complete now, train the echo canceler */
5548 @@ -3554,6 +3656,15 @@ static int zt_fixup(struct ast_channel *
5550 struct zt_pvt *p = newchan->tech_pvt;
5552 + if (newchan && newchan->tech_pvt) {
5553 + p = newchan->tech_pvt;
5557 + ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
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);
5570 + if (option_verbose > 2)
5571 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
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
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);
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;
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);
5594 @@ -4986,8 +5099,9 @@ static struct ast_frame *zt_read(struct
5596 } else if (f->frametype == AST_FRAME_DTMF) {
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;
5606 @@ -5062,7 +5176,9 @@ static int zt_write(struct ast_channel *
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);
5617 @@ -5130,7 +5246,7 @@ static int zt_indicate(struct ast_channe
5618 switch (condition) {
5619 case AST_CONTROL_BUSY:
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;
5626 @@ -5212,7 +5328,7 @@ static int zt_indicate(struct ast_channe
5627 case AST_CONTROL_CONGESTION:
5628 chan->hangupcause = AST_CAUSE_CONGESTION;
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;
5635 @@ -5406,8 +5522,12 @@ static struct ast_channel *zt_new(struct
5636 if (state == AST_STATE_RING)
5640 + if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
5642 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5643 - /* Only FXO signalled stuff can be picked up */
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;
5649 @@ -5537,6 +5657,7 @@ static void *ss_thread(void *data)
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);
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);
5665 - tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
5667 + network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
5669 + tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
5671 + /* cpe be quiet */
5672 + tone_zone_play_tone(p->subs[index].zfd, -1);
5675 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
5676 timeout = matchdigittimeout;
5678 @@ -6784,18 +6912,44 @@ static int handle_init_event(struct zt_p
5680 case ZT_EVENT_NOALARM:
5684 + if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
5685 + /* dont annoy BRI TE mode users with layer2layer alarms */
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);
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);
5698 case ZT_EVENT_ALARM:
5700 res = get_alarms(i);
5703 + if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
5704 + /* dont annoy BRI TE mode users with layer2layer alarms */
5706 + ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
5707 + manager_event(EVENT_FLAG_SYSTEM, "Alarm",
5709 + "Channel: %d\r\n",
5710 + alarm2str(res), i->channel);
5714 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
5715 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
5718 alarm2str(res), i->channel);
5720 /* fall thru intentionally */
5721 case ZT_EVENT_ONHOOK:
5723 @@ -6839,8 +6993,10 @@ static int handle_init_event(struct zt_p
5724 zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
5728 - res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
5729 + if (event != ZT_EVENT_ALARM) {
5731 + res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
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
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;
5743 pris[*span].dchannels[0] = 24 + offset;
5745 @@ -7391,6 +7549,11 @@ static struct zt_pvt *mkintf(int channel
5746 destroy_zt_pvt(&tmp);
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);
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
5760 pris[span].nodetype = conf.pri.nodetype;
5762 + if (conf.pri.nodetype == BRI_NETWORK_PTMP) {
5763 + pris[span].dchanavail[0] = DCHAN_AVAILABLE;
5764 + pri_find_dchan(&pris[span]);
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
5794 if (!backwards && (x >= pri->numchans))
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);
5801 @@ -8029,6 +8203,11 @@ static struct ast_channel *zt_request(co
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;
5809 + tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
5811 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
5813 @@ -8062,13 +8241,14 @@ next:
5814 *cause = AST_CAUSE_BUSY;
5815 } else if (groupmatched) {
5816 *cause = AST_CAUSE_CONGESTION;
5818 + *cause = AST_CAUSE_CONGESTION;
5827 static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
5829 @@ -8082,6 +8262,58 @@ static struct zt_pvt *pri_find_crv(struc
5833 +static int pri_find_tei(struct zt_pri *pri, q931_call *c, int tei)
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)) {
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;
5850 + if ((zhc->tei == tei) && ((zhc->cref == cref) || (cref == -1))) {
5854 + if (zhc) zhc = zhc->next;
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;
5864 + if (zhc == onhold) {
5866 + zhctemp->next = zhc->next;
5869 + pri->holded_calls = zhc->next;
5870 + zhc = pri->holded_calls;
5875 + if (zhc) zhc = zhc->next;
5886 static int pri_find_principle(struct zt_pri *pri, int channel)
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)
5894 + char tmpname[256];
5898 @@ -8141,6 +8375,7 @@ static int pri_fixup_principle(struct zt
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;
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);
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;
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);
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);
5931 + res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[principle]->law);
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);
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);
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;
5956 @@ -8183,7 +8453,9 @@ static int pri_fixup_principle(struct zt
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");
5967 @@ -8242,86 +8514,21 @@ static void *do_idle_thread(void *vchan)
5969 #error "Upgrade your libpri"
5971 -static void zt_pri_message(struct pri *pri, char *s)
5972 +static void zt_pri_message(char *s, int span)
5975 - int dchan = -1, span = -1;
5976 - int dchancount = 0;
5979 - for (x = 0; x < NUM_SPANS; x++) {
5980 - for (y = 0; y < NUM_DCHANS; y++) {
5981 - if (pris[x].dchans[y])
5984 - if (pris[x].dchans[y] == pri)
5993 - if ((dchan >= 0) && (span >= 0)) {
5994 - if (dchancount > 1)
5995 - ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
5997 - ast_verbose("%s", s);
5999 - ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
6001 - ast_verbose("%s", s);
6003 - ast_mutex_lock(&pridebugfdlock);
6005 - if (pridebugfd >= 0)
6006 - write(pridebugfd, s, strlen(s));
6008 - ast_mutex_unlock(&pridebugfdlock);
6009 + ast_verbose("%d %s", span, s);
6012 -static void zt_pri_error(struct pri *pri, char *s)
6013 +static void zt_pri_error(char *s, int span)
6016 - int dchan = -1, span = -1;
6017 - int dchancount = 0;
6020 - for (x = 0; x < NUM_SPANS; x++) {
6021 - for (y = 0; y < NUM_DCHANS; y++) {
6022 - if (pris[x].dchans[y])
6025 - if (pris[x].dchans[y] == pri)
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);
6038 - ast_log(LOG_ERROR, "%s", s);
6040 - ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
6042 - ast_log(LOG_ERROR, "%s", s);
6044 - ast_mutex_lock(&pridebugfdlock);
6046 - if (pridebugfd >= 0)
6047 - write(pridebugfd, s, strlen(s));
6049 - ast_mutex_unlock(&pridebugfdlock);
6050 + ast_log(LOG_WARNING, "%d %s", span, s);
6053 static int pri_check_restart(struct zt_pri *pri)
6055 + if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
6060 } while ((pri->resetpos < pri->numchans) &&
6061 @@ -8405,13 +8612,30 @@ static void apply_plan_to_number(char *b
6065 -static int zt_setlaw(int zfd, int law)
6068 - res = ioctl(zfd, ZT_SETLAW, &law);
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;
6076 + switch (callingplan) {
6077 + case PRI_INTERNATIONAL_ISDN:
6078 + snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
6080 + case PRI_NATIONAL_ISDN:
6081 + snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
6083 + case PRI_LOCAL_ISDN:
6084 + snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
6087 + snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
6090 + snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
6093 + snprintf(callerid, callerid_len, "%s", callingnum);
6098 static void *pri_dchannel(void *vpri)
6099 @@ -8591,15 +8815,44 @@ static void *pri_dchannel(void *vpri)
6100 /* Check for an event */
6102 res = ioctl(pri->fds[which], ZT_GETEVENT, &x);
6104 + if ((pri->nodetype != BRI_CPE) && (pri->nodetype != BRI_CPE_PTMP)) {
6105 + /* dont annoy BRI TE mode users with layer2layer alarms */
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);
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)) {
6115 + for (i=0; i<pri->numchans; i++) {
6116 + struct zt_pvt *p = pri->pvts[i];
6119 + if (p->pri && p->pri->pri) {
6120 + pri_destroycall(p->pri->pri, p->call);
6124 + ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
6127 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
6131 + pri_shutdown(pri->pri);
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;
6141 + pri->dchanavail[which] |= DCHAN_NOTINALARM;
6142 + pri_restart(pri->dchans[which]);
6147 @@ -8611,8 +8864,7 @@ static void *pri_dchannel(void *vpri)
6150 } else if (errno != EINTR)
6151 - ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
6153 + ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
6156 pri_dump_event(pri->dchans[which], e);
6157 @@ -8625,32 +8877,86 @@ static void *pri_dchannel(void *vpri)
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);
6171 + /* Note presense of D-channel */
6172 + time(&pri->lastreset);
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;
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);
6185 + if (option_verbose > 1)
6186 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
6188 + pri->dchanavail[which] |= DCHAN_UP;
6189 + if (!pri->pri) pri_find_dchan(pri);
6191 - /* Note presense of D-channel */
6192 - time(&pri->lastreset);
6193 + /* Note presense of D-channel */
6194 + time(&pri->lastreset);
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;
6203 - pri->resetting = 0;
6204 - /* Take the channels from inalarm condition */
6205 - for (i = 0; i < pri->numchans; i++)
6207 + pri->resetting = 0;
6208 + /* Take the channels from inalarm condition */
6209 + for (i = 0; i < pri->numchans; i++)
6211 pri->pvts[i]->inalarm = 0;
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];
6230 + // ast_log(LOG_NOTICE, "chan %d tei %d\n",i,p->tei);
6231 + if (p->tei == e->gen.tei) {
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);
6238 + ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
6241 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
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);
6252 + if (option_verbose > 1)
6253 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
6255 + pri->dchanavail[which] &= ~DCHAN_UP;
6256 + pri_find_dchan(pri);
6257 + if (!pri_is_up(pri)) {
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 */
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);
6270 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
6274 pri_hangup_all(p->realcall, pri);
6275 } else if (p->owner)
6276 @@ -8674,6 +8981,7 @@ static void *pri_dchannel(void *vpri)
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;
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)
6300 case PRI_EVENT_INFO_RECEIVED:
6301 chanpos = pri_find_principle(pri, e->ring.channel);
6303 @@ -8752,9 +9059,11 @@ static void *pri_dchannel(void *vpri)
6305 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
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);
6316 @@ -8766,6 +9075,14 @@ static void *pri_dchannel(void *vpri)
6317 zap_queue_frame(pri->pvts[chanpos], &f, pri);
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);
6325 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
6329 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
6331 @@ -8773,36 +9090,59 @@ static void *pri_dchannel(void *vpri)
6333 case PRI_EVENT_RING:
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);
6341 chanpos = pri_find_principle(pri, e->ring.channel);
6343 /* if no channel specified find one empty */
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);
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);
6365 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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);
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);
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);
6385 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
6390 + if (chanpos > -1) {
6391 + /* everything is ok with the b channel */
6392 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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 */
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);
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);
6414 ast_mutex_unlock(&crv->lock);
6415 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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)
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));
6436 + case PRES_NUMBER_NOT_AVAILABLE:
6437 + ast_copy_string(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
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';
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';
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';
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);
6472 + pri->pvts[chanpos]->exten[0] = '\0';
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';
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';
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';
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);
6506 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
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);
6512 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
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);
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);
6532 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
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);
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);
6547 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
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);
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);
6560 + /* overlapdial = yes and the extension can be valid */
6561 /* Get the use_callingpres state */
6562 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
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));
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);
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));
6578 + zt_enable_ec(pri->pvts[chanpos]); /* XXX rethink */
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);
6586 + if (!ast_strlen_zero(e->ring.callingnum)) {
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);
6591 + if (!ast_strlen_zero(e->ring.callingani)) {
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);
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);
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)
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;
6619 pthread_attr_destroy(&attr);
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));
6629 char calledtonstr[10];
6631 @@ -8995,26 +9422,43 @@ static void *pri_dchannel(void *vpri)
6632 ast_mutex_lock(&pri->lock);
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);
6644 + if (!ast_strlen_zero(e->ring.callingnum)) {
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);
6649 + if (!ast_strlen_zero(e->ring.callingani)) {
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);
6654 + if (!ast_strlen_zero(e->ring.useruserinfo)) {
6655 + pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
6659 ast_mutex_lock(&pri->lock);
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;
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';
6679 @@ -9023,9 +9467,9 @@ static void *pri_dchannel(void *vpri)
6680 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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);
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);
6690 case PRI_EVENT_RINGING:
6691 @@ -9041,7 +9485,7 @@ static void *pri_dchannel(void *vpri)
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;
6700 @@ -9073,9 +9517,16 @@ static void *pri_dchannel(void *vpri)
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);
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;
6715 #ifdef PRI_PROGRESS_MASK
6716 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
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);
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);
6728 if (!pri->pvts[chanpos]->proceeding) {
6729 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
6731 @@ -9169,6 +9626,295 @@ static void *pri_dchannel(void *vpri)
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, "");
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);
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;
6752 + zpc = malloc(sizeof(struct zt_suspended_call));
6754 + ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
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;
6768 + pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
6769 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
6773 + pri_suspend_reject(pri->pri, e->suspend_req.call, "");
6775 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
6778 + case PRI_EVENT_RESUME_REQ:
6779 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
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);
6787 + } else if (!pri->pvts[chanpos]) {
6788 + pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
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;
6797 + char extenstr[255], temp[255];
6799 + zpcl = pri->suspended_calls;
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))) {
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;
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);
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);
6820 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
6823 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
6825 + c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
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]);
6832 + ast_log(LOG_ERROR, "unable to start pbx\n");
6836 + zpc->next = zpcl->next;
6841 + pri->suspended_calls = zpcl->next;
6843 + zpcl = pri->suspended_calls;
6847 + snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
6848 + pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
6852 + if (zpcl) zpcl = zpcl->next;
6855 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
6857 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
6859 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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);
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);
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;
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));
6884 + ast_log(LOG_ERROR, "unable to malloc zt_holded_call\n");
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;
6899 + /* put channel on hold */
6900 + ast_masq_hold_call(ast_bridged_channel(p->owner), p->owner);
6902 + pri_hold_acknowledge(pri->pri, e->hold_req.call);
6904 + p->call = NULL; // free the bchannel withouth destroying the call
6907 + // cant hold a non-bridge,...yet
6909 + // make a fake channel
6914 + pri_hold_reject(pri->pri, e->hold_req.call);
6917 + pri_hold_reject(pri->pri, e->hold_req.call);
6919 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
6921 + pri_hold_reject(pri->pri, e->hold_req.call);
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);
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);
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);
6941 + if (chanpos > -1) {
6942 + struct zt_holded_call *onhold = NULL;
6943 + int retrieved = 0;
6945 + struct app_tmp *tmp;
6946 + pthread_attr_t attr;
6949 + onhold = pri_get_callonhold(pri, e->retrieve_req.cref, e->retrieve_req.tei);
6952 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
6955 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
6956 + // found a parked call
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);
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);
6967 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
6969 + c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 0, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
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]);
6978 + ast_log(LOG_ERROR, "unable to start pbx\n");
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);
6985 + // the magic begins here: ....
6986 + tmp = malloc(sizeof(struct app_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);
6993 + pri_destroy_callonhold(pri, onhold);
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));
7007 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
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);
7018 + if (chanpos > -1) {
7019 + if (pri->pvts[chanpos]->owner) {
7020 + // ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
7024 case PRI_EVENT_ANSWER:
7025 chanpos = pri_find_principle(pri, e->answer.channel);
7027 @@ -9181,6 +9927,7 @@ static void *pri_dchannel(void *vpri)
7028 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
7030 ast_mutex_lock(&pri->pvts[chanpos]->lock);
7031 + pri->pvts[chanpos]->tei = e->answer.tei;
7032 /* Now we can do call progress detection */
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]);
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]);
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);
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;
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;
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;
7077 + if (e->hangup.aoc_units > -1) {
7078 + if (pri->pvts[chanpos]->owner) {
7080 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
7081 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
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");
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)
7092 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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);
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);
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);
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);
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);
7120 + if (pri->nodetype == BRI_NETWORK_PTMP) {
7121 + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
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);
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);
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) {
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) {
7147 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
7148 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
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");
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;
7162 + onhold = pri_get_callonhold(pri, -1, e->hangup.tei);
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);
7170 + if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
7171 + ast_indicate(transferee, AST_CONTROL_RINGING);
7174 + pri->pvts[chanpos]->owner->_softhangup &= ~AST_SOFTHANGUP_DEV;
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");
7180 + /* beware of zombies!!! */
7181 + ast_set_flag(transferee, AST_FLAG_ZOMBIE);
7182 + pri->pvts[chanpos]->owner = NULL;
7183 + pri->pvts[chanpos]->tei = -1;
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);
7192 + } else if (pri->pvts[chanpos]->pritransfer == 1) {
7193 + /* we use ECT transfers, so just ignore this */
7197 + if (transfer_ok) {
7198 + onhold->alreadyhungup = 1;
7199 + pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
7202 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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;
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;
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;
7230 #ifdef SUPPORT_USERUSER
7231 @@ -9366,9 +10217,39 @@ static void *pri_dchannel(void *vpri)
7233 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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);
7239 + // check holded_calls!!!
7240 + struct zt_holded_call *onhold = NULL;
7242 + onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
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);
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);
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) {
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");
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);
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)
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)
7283 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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);
7298 + ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
7300 f.subclass = AST_CONTROL_HOLD;
7301 zap_queue_frame(pri->pvts[chanpos], &f, pri);
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));
7308 + ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
7310 f.subclass = AST_CONTROL_UNHOLD;
7311 zap_queue_frame(pri->pvts[chanpos], &f, pri);
7313 @@ -9497,6 +10393,77 @@ static void *pri_dchannel(void *vpri)
7314 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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);
7324 + /* search for cref/tei in held calls */
7325 + onhold = pri_get_callonhold(pri, e->facility.cref, e->facility.tei);
7327 + chan = ast_get_holded_call(onhold->uniqueid);
7328 + onhold->alreadyhungup = 1;
7332 + pri_hangup(pri->pri, e->facility.call, 16, -1);
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);
7339 + pri_hangup(pri->pri, e->facility.call, 16, -1);
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 */
7352 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
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);
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);
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");
7367 + /* beware of zombies !!! */
7368 + ast_set_flag(chan, AST_FLAG_ZOMBIE);
7369 + // chan->zombie = 1;
7372 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
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);
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);
7383 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
7385 + ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
7389 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
7391 @@ -9558,7 +10525,7 @@ static int start_pri(struct zt_pri *pri)
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
7402 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
7409 + return RESULT_SHOWUSAGE;
7411 if (!strncasecmp(argv[1], "set", 3)) {
7414 return RESULT_SHOWUSAGE;
7416 - if (ast_strlen_zero(argv[4]))
7417 + if (!argv[4] || ast_strlen_zero(argv[4]))
7418 return RESULT_SHOWUSAGE;
7421 + return RESULT_SHOWUSAGE;
7423 + if (!argv[6] || ast_strlen_zero(argv[6]))
7424 + return RESULT_SHOWUSAGE;
7426 + span = atoi(argv[6]);
7427 + if ((span < 1) && (span > NUM_SPANS)) {
7428 + return RESULT_SUCCESS;
7432 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
7434 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
7435 return RESULT_SUCCESS;
7438 - ast_mutex_lock(&pridebugfdlock);
7440 - if (pridebugfd >= 0)
7441 - close(pridebugfd);
7443 - pridebugfd = myfd;
7444 - ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
7446 - ast_mutex_unlock(&pridebugfdlock);
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);
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);
7461 + ast_mutex_unlock(&pris[x].lock);
7464 + ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
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);
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;
7479 + for (x=0; x < NUM_SPANS; x++) {
7480 + ast_mutex_lock(&pris[x].lock);
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);
7491 + ast_mutex_unlock(&pris[x].lock);
7494 + ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
7497 return RESULT_SUCCESS;
7498 @@ -9692,6 +10697,7 @@ static int handle_pri_debug(int fd, int
7503 static int handle_pri_no_debug(int fd, int argc, char *argv[])
7506 @@ -9841,10 +10847,6 @@ static int handle_pri_show_debug(int fd,
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);
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";
7521 +static char bri_debug_help[] =
7522 + "Usage: bri debug span <span>\n"
7523 + " Enables debugging on a given BRI span\n";
7525 +static char bri_no_debug_help[] =
7526 + "Usage: bri no debug span <span>\n"
7527 + " Disables debugging on a given BRI span\n";
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";
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" },
7540 + { { "bri", "debug", "span", NULL }, handle_pri_debug,
7541 + "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
7543 + { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
7544 + "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
7546 + { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
7547 + "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
7549 { { "pri", "set", "debug", "file", NULL },
7550 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
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" },
7556 +static char *zapCD_tdesc = "Call Deflection";
7557 +static char *zapCD_app = "zapCD";
7558 +static char *zapCD_synopsis = "Call Deflection";
7560 +static int app_zapCD(struct ast_channel *chan, void *data)
7562 + struct zt_pvt *p = chan->tech_pvt;
7564 + if((!p->pri) || (!p->pri->pri)) {
7569 + ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
7572 + return pri_deflect(p->pri->pri, p->call, data);
7575 +static char *zapInband_tdesc = "Inband Call Progress (pre-answer)";
7576 +static char *zapInband_app = "zapInband";
7577 +static char *zapInband_synopsis = "Inband Call Progress";
7579 +static int app_zapInband(struct ast_channel *chan, void *data)
7581 + struct zt_pvt *p = chan->tech_pvt;
7583 + return pri_acknowledge(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1);
7586 #endif /* HAVE_PRI */
7588 +static int app_zapEC(struct ast_channel *chan, void *data)
7591 + struct zt_pvt *p = NULL;
7594 + ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
7596 + if (chan && !strcasecmp("ZAP",chan->tech->type)) {
7597 + p = chan->tech_pvt;
7598 + if (!p) return res;
7599 + if (!strcasecmp("on",(char *)data)) {
7602 + if (option_verbose > 3) {
7603 + ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
7605 + } else if (!strcasecmp("off",(char *)data)) {
7608 + if (option_verbose > 3) {
7609 + ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
7612 + ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
7615 + ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
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";
7626 static int zap_destroy_channel(int fd, int argc, char **argv)
7629 @@ -10484,8 +11575,11 @@ static int __unload_module(void)
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);
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;
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;
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;
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)
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);
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));
7725 memset(round_robin, 0, sizeof(round_robin));
7726 @@ -11512,6 +12644,7 @@ static int zt_sendtext(struct ast_channe
7731 index = zt_get_index(c, p, 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
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
7742 ; priindication = outofband
7744 +; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
7746 +; Configure how transfers are initiated. ECT should be preferred
7748 +; no: no transfers allowed (results in hangup)
7749 +; ect: use ECT (facility)
7750 +; hangup: transfer on hangup (if your phones dont support ECT)
7752 +; pritransfer = ect
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);
7764 + if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
7765 + config->flags = 0;
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
7777 +#include <libgsmat.h>
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);
7794 +static char gsm_modem_pin[20];
7795 +static char gsm_modem_exten[AST_MAX_EXTENSION];
7797 static int ifcount = 0;
7799 @@ -251,7 +257,7 @@ static int restart_monitor(void);
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);
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);
7807 /*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
7808 @@ -366,6 +372,19 @@ struct zt_pri {
7815 + ast_mutex_t lock; /* Mutex */
7818 + struct gsm_modul *modul;
7821 + char exten[AST_MAX_EXTENSION]; /* Where to idle extra calls */
7822 + struct zt_pvt *pvt;
7826 static struct zt_pri pris[NUM_SPANS];
7828 @@ -394,6 +413,7 @@ struct zt_pri;
7829 #define POLARITY_REV 1
7833 static struct zt_distRings drings;
7835 struct distRingData {
7836 @@ -605,6 +625,9 @@ static struct zt_pvt {
7841 + struct zt_gsm gsm;
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";
7864 @@ -1791,7 +1816,7 @@ static inline int zt_confmute(struct zt_
7868 - if (p->sig == SIG_PRI) {
7869 + if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
7871 res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
7873 @@ -2206,6 +2231,25 @@ static int zt_call(struct ast_channel *a
7874 p->dialdest[0] = '\0';
7875 disable_dtmf_detect(p);
7879 + if (p->gsm.modul) {
7880 + c = strchr(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);
7892 + ast_mutex_unlock(&p->gsm.lock);
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
7903 - if (p->sig && (p->sig != SIG_PRI))
7905 + if (p->gsm.modul) {
7906 + if (!p->alreadyhungup)
7907 + gsm_hangup(p->gsm.modul);
7910 + if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_GSM))
7911 res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
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
7920 + if (p->gsm.modul) {
7921 + gsm_answer(p->gsm.modul);
7926 ast_mutex_unlock(&p->lock);
7928 @@ -7384,6 +7441,10 @@ static int pri_create_spanmap(int span,
7933 +static void *gsm_dchannel(void *vgsm);
7936 static struct zt_pvt *mkintf(int channel, struct zt_chan_conf conf, struct zt_pri *pri, int reloading)
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
7944 + if (conf.chan.sig == SIG_GSM) {
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;
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));
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);
7969 + if (ast_pthread_create(&tmp->gsm.master, NULL, gsm_dchannel, &tmp->gsm)) {
7970 + zt_close(tmp->gsm.fd);
7975 conf.chan.sig = tmp->sig;
7976 conf.chan.radio = tmp->radio;
7977 @@ -7895,6 +7987,12 @@ static inline int available(struct zt_pv
7982 + if (p->gsm.modul) {
7983 + return gsm_available(p->gsm.modul);
7987 if (!(p->radio || (p->oprmode < 0)))
7989 if (!p->sig || (p->sig == SIG_FXSLS))
7990 @@ -8249,6 +8347,235 @@ next:
7995 +static int zt_reset_span(int span, int sleep) {
7999 + ctl = open("/dev/zap/ctl", O_RDWR);
8001 + ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
8004 + ast_verbose(VERBOSE_PREFIX_2 "Shutting down span %d. Please wait...\n", span);
8005 + res = ioctl(ctl, ZT_SHUTDOWN, &span);
8007 + ast_log(LOG_WARNING, "error shutting down span %d\n", span);
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);
8014 + ast_log(LOG_WARNING, "error starting up span %d\n", span);
8017 + ast_verbose(VERBOSE_PREFIX_2 "Reset of span %d completed.\n", span);
8022 +static void handle_gsm_event(struct zt_gsm *gsm, gsm_event *e)
8024 + struct ast_channel *c = NULL;
8025 + int law = ZT_LAW_ALAW;
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;
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;
8043 + ast_mutex_unlock(&gsm->pvt->lock); */
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);
8050 + strncpy(gsm->pvt->cid_name, "CID withheld", sizeof(gsm->pvt->cid_name));
8052 + if (!ast_strlen_zero(gsm->exten)) {
8053 + strncpy(gsm->pvt->exten, gsm->exten, sizeof(gsm->pvt->exten) - 1);
8055 + gsm->pvt->exten[0] = 's';
8056 + gsm->pvt->exten[1] = '\0';
8058 + c = zt_new(gsm->pvt, AST_STATE_RING, 1, SUB_REAL, ZT_LAW_ALAW, AST_TRANS_CAP_SPEECH);
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);
8068 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", gsm->pvt->channel);
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);
8073 + ast_mutex_unlock(&gsm->pvt->lock);
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;
8083 + ast_mutex_unlock(&gsm->pvt->lock);
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;
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);
8099 +// gsm_poweroff(gsm->modul);
8100 + zt_reset_span(gsm->span, 8000);
8101 +// gsm_restart(gsm->modul, 10000);
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);
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);
8116 + case GSM_EVENT_PIN_REQUIRED:
8117 + gsm_send_pin(gsm->modul, gsm->pin);
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",
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);
8136 + ast_log(LOG_WARNING,"!! Unknown GSM event %d !!\n", e->e);
8140 +static void *gsm_dchannel(void *vgsm)
8142 + struct zt_gsm *gsm = vgsm;
8144 + struct timeval tv = {0,0}, *next;
8145 + fd_set rfds, efds;
8148 + if (!gsm) return NULL;
8150 + if (!gsm->modul) {
8151 + fprintf(stderr, "No gsm_mod\n");
8154 + gsm_set_debug(gsm->modul, GSM_DEBUG_NONE);
8157 + /* Run the D-Channel */
8160 + FD_SET(gsm->fd, &rfds);
8161 + FD_SET(gsm->fd, &efds);
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;
8171 + if (tv.tv_sec < 0) {
8176 + res = select(gsm->fd + 1, &rfds, NULL, &efds, next ? &tv : NULL);
8179 + ast_mutex_lock(&gsm->lock);
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));
8191 + e = gsm_check_event(gsm->modul, 0);
8195 + handle_gsm_event(gsm, e);
8197 + ast_mutex_unlock(&gsm->lock);
8199 + res = ioctl(gsm->fd, ZT_GETEVENT, &x);
8203 + case ZT_EVENT_NOALARM:
8204 + ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", gsm->span);
8206 + gsm_restart(gsm->modul, 10000);
8208 + case ZT_EVENT_ALARM:
8209 + ast_log(LOG_NOTICE, "Alarm detected on span %d\n", gsm->span);
8212 + fprintf(stderr, "Got event on GSM interface: %d\n", x);
8224 static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
8226 @@ -8524,6 +8851,18 @@ static void zt_pri_error(char *s, int sp
8227 ast_log(LOG_WARNING, "%d %s", span, s);
8231 +static void zt_gsm_message(char *s, int channel)
8233 + ast_verbose("GSM %d: %s", channel, s);
8236 +static void zt_gsm_error(char *s, int channel)
8238 + ast_log(LOG_WARNING, "GSM %d: %s", channel, s);
8242 static int pri_check_restart(struct zt_pri *pri)
8244 if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
8245 @@ -10957,6 +11296,243 @@ static int app_zapInband(struct ast_chan
8247 #endif /* HAVE_PRI */
8250 +static int handle_zap_reset_span(int fd, int argc, char *argv[])
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;
8261 + if (zt_reset_span(span, sleep)) {
8262 + return RESULT_FAILURE;
8264 + return RESULT_SUCCESS;
8267 +static int handle_gsm_debug_helper(int fd, int channel, int debug)
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;
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;
8287 + ast_cli(fd, "No GSM running on channel %d\n", channel);
8288 + return RESULT_SUCCESS;
8293 +static int handle_gsm_debug(int fd, int argc, char *argv[])
8295 +/* gsm debug channel <channel> */
8298 + return RESULT_SHOWUSAGE;
8300 + channel = atoi(argv[3]);
8301 + return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_AT);
8304 +static int handle_gsm_no_debug(int fd, int argc, char *argv[])
8306 +/* gsm no debug channel <channel> */
8309 + return RESULT_SHOWUSAGE;
8311 + channel = atoi(argv[4]);
8312 + return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_NONE);
8315 +static char zap_reset_help[] =
8316 + "Usage: zap reset span <span>\n"
8317 + " Reset/Restart a zaptel span\n";
8319 +static char gsm_debug_help[] =
8320 + "Usage: gsm debug channel <channel>\n"
8321 + " Enables debugging on a given GSM channel\n";
8323 +static char gsm_no_debug_help[] =
8324 + "Usage: gsm no debug channel <channel>\n"
8325 + " Disables debugging on a given GSM channel\n";
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},
8338 +static char gsm_send_pdu_help[] =
8339 + "Usage: gsm send pdu <channel> <pdu>\n"
8340 + " Sends a PDU on a GSM channel\n";
8344 +static int handle_gsm_send_pdu(int fd, int argc, char *argv[])
8346 +/* gsm send sms <channel> <destination> <message> */
8348 + struct zt_pvt *pvt = NULL;
8350 + return RESULT_SHOWUSAGE;
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;
8359 + if (pvt->channel == channel) {
8361 + ast_cli(fd, "Channel in use.\n");
8362 + return RESULT_FAILURE;
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;
8373 + return RESULT_SUCCESS;
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 };
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";
8385 +static int handle_gsm_send_sms(int fd, int argc, char *argv[])
8387 +/* gsm send sms <channel> <destination> <message> */
8389 + struct zt_pvt *pvt = NULL;
8391 + return RESULT_SHOWUSAGE;
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;
8400 + if (pvt->channel == channel) {
8402 + ast_cli(fd, "Channel in use.\n");
8403 + return RESULT_FAILURE;
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;
8414 + return RESULT_SUCCESS;
8417 +static int zt_gsm_sendtext(struct ast_channel *chan, const char * dest, const char *text, int ispdu) {
8418 + struct zt_pvt *pvt = NULL;
8420 + pvt = chan->tech_pvt;
8422 + if (!pvt) return -1;
8424 + /* parse dialstring */
8425 + c = strrchr(dest, '/');
8431 + ast_mutex_lock(&pvt->lock);
8433 + gsm_sms_send_pdu(pvt->gsm.modul, (char *)text);
8435 + gsm_sms_send_text(pvt->gsm.modul, c, (char *)text);
8437 + ast_mutex_unlock(&pvt->lock);
8438 + gsm_wait(pvt->gsm.modul);
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 };
8445 +static char gsm_show_status_help[] =
8446 + "Usage: gsm show status <channel>>\n"
8447 + " Displays status information about the GSM channel.\n";
8450 +static int handle_gsm_show_status(int fd, int argc, char *argv[])
8453 + struct zt_pvt *pvt = NULL;
8455 + return RESULT_SHOWUSAGE;
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;
8464 + if (pvt->channel == channel) {
8466 + ast_cli(fd, "Channel in use.\n");
8467 + return RESULT_FAILURE;
8469 + ast_mutex_lock(&pvt->lock);
8470 + gsm_request_status(pvt->gsm.modul);
8471 + ast_mutex_unlock(&pvt->lock);
8472 + return RESULT_SUCCESS;
8478 + return RESULT_SUCCESS;
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 };
8484 +#endif /* HAVE_GSMAT */
8486 static int app_zapEC(struct ast_channel *chan, void *data)
8489 @@ -11578,6 +12154,12 @@ static int __unload_module(void)
8490 ast_unregister_application(zapCD_app);
8491 ast_unregister_application(zapInband_app);
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);
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;
8507 + } else if (!strcasecmp(v->value, "gsm")) {
8508 + confp->chan.sig = SIG_GSM;
8509 + confp->chan.radio = 0;
8512 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
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);
8530 + gsm_set_error(zt_gsm_error);
8531 + gsm_set_message(zt_gsm_message);
8534 /* Make sure we can register our Zap channel type */
8536 @@ -12612,6 +13207,12 @@ static int load_module(void)
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));
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]));
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)
8553 -static int zt_sendtext(struct ast_channel *c, const char *text)
8555 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text);
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)) {
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);
8567 + } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
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) {
8580 + ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP ISDN channel\n");
8583 + return zt_pri_sendtext(c, text);
8585 + } else if (p->sig == SIG_GSM) {
8587 + return zt_gsm_sendtext(c, dest, text, ispdu);
8590 + return zt_tdd_sendtext(c, text);
8595 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text)
8597 #define END_SILENCE_LEN 400
8598 #define HEADER_MS 50
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'])
8605 +AST_EXT_LIB_SETUP([GSMAT], [GSM AT command signalling], [gsmat])
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])
8613 +AST_EXT_LIB_CHECK([GSMAT], [gsmat], [gsm_new_call], [libgsmat.h])
8615 AST_EXT_LIB_CHECK([IKSEMEL], [iksemel], [iks_start_sasl], [iksemel.h])
8617 if test "${PBX_IKSEMEL}" = 1; then
8618 diff -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
8622 <depend>zaptel</depend>
8623 <depend>tonezone</depend>
8624 <depend>res_features</depend>
8625 + <depend>gsmat</depend>
8629 Tylko w asterisk-1.4.17/channels: chan_zap.c~
8630 diff -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
8634 <depend>zaptel</depend>
8635 <depend>tonezone</depend>
8636 <depend>res_features</depend>
8637 + <depend>gsmat</depend>
8640 Tylko w asterisk-1.4.17/channels: .chan_zap.moduleinfo~
8641 diff -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
8645 <depend>zaptel</depend>
8646 <depend>tonezone</depend>
8647 <depend>res_features</depend>
8648 + <depend>gsmat</depend>
8651 <member name="chan_vpb" displayname="" remove_on_change="channels/chan_vpb.oo channels/chan_vpb.so">
8652 Tylko w asterisk-1.4.17/channels: .moduleinfo~
8653 diff -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
8657 <depend>zaptel</depend>
8658 <depend>tonezone</depend>
8659 <depend>res_features</depend>
8660 + <depend>gsmat</depend>
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
8667 GSM_INCLUDE=@GSM_INCLUDE@
8670 +GSMAT_INCLUDE=@GSMAT_INCLUDE@
8671 +GSMAT_LIB=@GSMAT_LIB@
8673 GTK_INCLUDE=@GTK_INCLUDE@
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
8680 FREETDS=@PBX_FREETDS@