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 @@ -2427,6 +2427,7 @@ static void ast_readconfig(void)
61 ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
62 ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
63 ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
64 + ast_copy_string(ast_config_AST_SYSTEM_NAME, AST_SYSTEM_NAME, sizeof(ast_config_AST_SYSTEM_NAME));
66 /* no asterisk.conf? no problem, use buildtime config! */
68 @@ -2551,6 +2552,8 @@ static void ast_readconfig(void)
69 ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
70 } else if (!strcasecmp(v->name, "systemname")) {
71 ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
72 + } else if (!strcasecmp(v->name, "uniquename")) {
73 + ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
74 } else if (!strcasecmp(v->name, "languageprefix")) {
75 ast_language_is_prefix = ast_true(v->value);
77 --- a/include/asterisk/agi.h
78 +++ b/include/asterisk/agi.h
79 @@ -30,6 +30,7 @@ extern "C" {
80 typedef struct agi_state {
81 int fd; /* FD for general output */
82 int audio; /* FD for audio output */
83 + int audio_in; /* FD for audio output */
84 int ctrl; /* FD for input control */
85 unsigned int fast:1; /* flag for fast agi or not */
90 * the project provides a web site, mailing lists and IRC
91 * channels for your use.
93 + * Copyright (C) 2005 Junghanns.NET GmbH
94 + * Klaus-Peter Junghanns <kpj@junghanns.net>
96 * This program is free software, distributed under the terms of
97 * the GNU General Public License Version 2. See the LICENSE file
98 * at the top of the source tree.
99 @@ -75,16 +78,19 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
101 static char *app = "AGI";
103 +static char *xapp = "XAGI";
105 static char *eapp = "EAGI";
107 static char *deadapp = "DeadAGI";
109 static char *synopsis = "Executes an AGI compliant application";
110 +static char *xsynopsis = "Executes an XAGI compliant application";
111 static char *esynopsis = "Executes an EAGI compliant application";
112 static char *deadsynopsis = "Executes AGI on a hungup channel";
114 static char *descrip =
115 -" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
116 +" [E|Dead|X]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
117 "program on a channel. AGI allows Asterisk to launch external programs\n"
118 "written in any language to control a telephony channel, play audio,\n"
119 "read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
120 @@ -97,6 +103,8 @@ static char *descrip =
121 "variable to \"no\" before executing the AGI application.\n"
122 " Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
123 "on file descriptor 3\n\n"
124 +"Using 'XAGI' provides enhanced AGI, with incoming audio available out of band"
125 +" on file descriptor 3 and outgoing audio available out of band on file descriptor 4\n\n"
126 " Use the CLI command 'agi show' to list available agi commands\n"
127 " This application sets the following channel variable upon completion:\n"
128 " AGISTATUS The status of the attempt to the run the AGI script\n"
129 @@ -236,13 +244,14 @@ static enum agi_result launch_netscript(
130 return AGI_RESULT_SUCCESS_FAST;
133 -static enum agi_result launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
134 +static enum agi_result launch_script(char *script, char *argv[], int *fds, int *efd, int *efd2, int *opid)
144 sigset_t signal_set, old_set;
145 @@ -287,6 +296,33 @@ static enum agi_result launch_script(cha
146 return AGI_RESULT_FAILURE;
150 + if (pipe(audio2)) {
151 + ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
158 + return AGI_RESULT_FAILURE;
160 + res = fcntl(audio2[0], F_GETFL);
162 + res = fcntl(audio2[0], F_SETFL, res | O_NONBLOCK);
164 + ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
173 + return AGI_RESULT_FAILURE;
177 /* Block SIGHUP during the fork - prevents a race */
178 sigfillset(&signal_set);
179 @@ -322,6 +358,11 @@ static enum agi_result launch_script(cha
181 close(STDERR_FILENO + 1);
184 + dup2(audio2[1], STDERR_FILENO + 2);
186 + close(STDERR_FILENO + 2);
189 /* Before we unblock our signals, return our trapped signals back to the defaults */
190 signal(SIGHUP, SIG_DFL);
191 @@ -339,7 +380,7 @@ static enum agi_result launch_script(cha
194 /* Close everything but stdin/out/error */
195 - for (x=STDERR_FILENO + 2;x<1024;x++)
196 + for (x=STDERR_FILENO + 3;x<1024;x++)
200 @@ -359,12 +400,19 @@ static enum agi_result launch_script(cha
207 /* close what we're not using in the parent */
220 return AGI_RESULT_SUCCESS;
221 @@ -394,7 +442,7 @@ static void setup_env(struct ast_channel
222 fdprintf(fd, "agi_context: %s\n", chan->context);
223 fdprintf(fd, "agi_extension: %s\n", chan->exten);
224 fdprintf(fd, "agi_priority: %d\n", chan->priority);
225 - fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
226 + fdprintf(fd, "agi_enhanced: %d%s\n", enhanced, ".0");
228 /* User information */
229 fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
230 @@ -1835,8 +1883,13 @@ static enum agi_result run_agi(struct as
232 enum agi_result returnstatus = AGI_RESULT_SUCCESS;
234 + struct ast_frame fr;
235 char buf[AGI_BUF_LEN];
236 + char audiobuf[AGI_BUF_LEN];
242 /* how many times we'll retry if ast_waitfor_nandfs will return without either
243 channel or file descriptor in case select is interrupted by a system call (EINTR) */
244 @@ -1850,10 +1903,22 @@ static enum agi_result run_agi(struct as
245 return AGI_RESULT_FAILURE;
248 - setup_env(chan, request, agi->fd, (agi->audio > -1));
249 + if (agi->audio > -1) {
252 + if (agi->audio_in > -1) {
255 + setup_env(chan, request, agi->fd, enhanced);
256 + fds[0] = agi->ctrl;
257 + fds[1] = agi->audio_in;
260 - c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
261 + if (agi->audio_in > -1) {
262 + c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, fds, 2, NULL, &outfd, &ms);
264 + c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
267 retry = AGI_NANDFS_RETRY;
268 /* Idle the channel until we get a command */
269 @@ -1871,6 +1936,16 @@ static enum agi_result run_agi(struct as
272 } else if (outfd > -1) {
273 + if ((agi->audio_in > -1) && (outfd == agi->audio_in)) {
274 + audiobytes = read(agi->audio_in, audiobuf, sizeof(audiobuf));
275 + if (audiobytes > 0) {
276 + fr.frametype = AST_FRAME_VOICE;
277 + fr.subclass = AST_FORMAT_SLINEAR;
278 + fr.datalen = audiobytes;
279 + fr.data = audiobuf;
280 + ast_write(chan, &fr);
283 size_t len = sizeof(buf);
286 @@ -1922,6 +1997,7 @@ static enum agi_result run_agi(struct as
287 if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
293 ast_log(LOG_WARNING, "No channel, no fd?\n");
294 @@ -2030,6 +2106,7 @@ static int agi_exec_full(struct ast_chan
302 @@ -2056,12 +2133,13 @@ static int agi_exec_full(struct ast_chan
305 ast_replace_sigchld();
306 - res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
307 + res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, (enhanced == 2) ? &efd2 : NULL, &pid);
308 if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
313 + agi.audio_in = efd2;
314 agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
315 res = run_agi(chan, argv[0], &agi, pid, &status, dead);
316 /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
317 @@ -2071,6 +2149,8 @@ static int agi_exec_full(struct ast_chan
324 ast_unreplace_sigchld();
325 ast_module_user_remove(u);
326 @@ -2119,6 +2199,35 @@ static int eagi_exec(struct ast_channel
330 +static int xagi_exec(struct ast_channel *chan, void *data)
332 + int readformat, writeformat;
335 + if (chan->_softhangup)
336 + ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
337 + readformat = chan->readformat;
338 + if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
339 + ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
342 + writeformat = chan->writeformat;
343 + if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
344 + ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
347 + res = agi_exec_full(chan, data, 2, 0);
349 + if (ast_set_read_format(chan, readformat)) {
350 + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
352 + if (ast_set_write_format(chan, writeformat)) {
353 + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(writeformat));
359 static int deadagi_exec(struct ast_channel *chan, void *data)
361 if (!ast_check_hangup(chan))
362 @@ -2174,6 +2283,7 @@ static int unload_module(void)
364 ast_module_user_hangup_all();
365 ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
366 + ast_unregister_application(xapp);
367 ast_unregister_application(eapp);
368 ast_unregister_application(deadapp);
369 return ast_unregister_application(app);
370 @@ -2184,6 +2294,7 @@ static int load_module(void)
371 ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
372 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
373 ast_register_application(eapp, eagi_exec, esynopsis, descrip);
374 + ast_register_application(xapp, xagi_exec, xsynopsis, descrip);
375 return ast_register_application(app, agi_exec, synopsis, descrip);
379 +++ b/agi/xagi-test.c
382 + * Asterisk -- A telephony toolkit for Linux.
384 + * XAGI sample script
386 + * Copyright (C) 2005 Junghanns.NET GmbH
387 + * Klaus-Peter Junghanns <kpj@junghanns.net>
389 + * based on eagi-test.c
391 + * This program is free software, distributed under the terms of
392 + * the GNU General Public License
400 +#include <sys/select.h>
402 +#include <solaris-compat/compat.h>
405 +#define AUDIO_FILENO_IN (STDERR_FILENO + 1)
406 +#define AUDIO_FILENO_OUT (STDERR_FILENO + 2)
408 +static int read_environment(void)
412 + /* Read environment */
414 + fgets(buf, sizeof(buf), stdin);
417 + buf[strlen(buf) - 1] = '\0';
418 + /* Check for end of environment */
421 + val = strchr(buf, ':');
423 + fprintf(stderr, "Invalid environment: '%s'\n", buf);
430 + // fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val);
432 + /* Load into normal environment */
433 + setenv(buf, val, 1);
436 + /* Never reached */
440 +static void app_echo(void)
445 + static char astresp[256];
446 + char audiobuf[16000]; /* 1 second of audio */
449 + FD_SET(STDIN_FILENO, &fds);
450 + FD_SET(AUDIO_FILENO_IN, &fds);
451 + /* Wait for *some* sort of I/O */
452 + res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
454 + fprintf(stderr, "Error in select: %s\n", strerror(errno));
457 + if (FD_ISSET(STDIN_FILENO, &fds)) {
458 + fgets(astresp, sizeof(astresp), stdin);
462 + astresp[strlen(astresp) - 1] = '\0';
463 + fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
466 + if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
467 + /* what goes in.... */
468 + res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
471 + /* must come out */
472 + write(AUDIO_FILENO_OUT, audiobuf, bytes);
478 +static char *wait_result(void)
482 + static char astresp[256];
483 + char audiobuf[4096];
486 + FD_SET(STDIN_FILENO, &fds);
487 + FD_SET(AUDIO_FILENO_IN, &fds);
488 + /* Wait for *some* sort of I/O */
489 + res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
491 + fprintf(stderr, "Error in select: %s\n", strerror(errno));
494 + if (FD_ISSET(STDIN_FILENO, &fds)) {
495 + fgets(astresp, sizeof(astresp), stdin);
497 + fprintf(stderr, "Got hungup on apparently\n");
500 + astresp[strlen(astresp) - 1] = '\0';
501 + fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
504 + if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
505 + res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
506 + /* drop it, like it's hot */
512 +static char *run_command(char *command)
514 + fprintf(stdout, "%s\n", command);
515 + return wait_result();
519 +static int run_script(void)
522 + res = run_command("STREAM FILE demo-echotest \"\"");
524 + fprintf(stderr, "Failed to execute command\n");
531 +int main(int argc, char *argv[])
536 + /* Setup stdin/stdout for line buffering */
538 + setlinebuf(stdout);
539 + if (read_environment()) {
540 + fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
543 + tmp = getenv("agi_enhanced");
545 + if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
549 + fprintf(stderr, "No XAGI services available. Use XAGI, not AGI or EAGI\n");
560 .PHONY: clean all uninstall
562 -AGIS=agi-test.agi eagi-test eagi-sphinx-test jukebox.agi
563 +AGIS=agi-test.agi eagi-test eagi-sphinx-test jukebox.agi xagi-test
565 ifeq ($(OSARCH),SunOS)
567 @@ -38,7 +38,7 @@ uninstall:
568 for x in $(AGIS); do rm -f $(DESTDIR)$(AGI_DIR)/$$x ; done
571 - rm -f *.so *.o look eagi-test eagi-sphinx-test
572 + rm -f *.so *.o look eagi-test eagi-sphinx-test xagi-test
573 rm -f .*.o.d .*.oo.d *.s *.i
577 +++ b/apps/app_segfault.c
580 + * Segfault application
582 + * An application to provoke a segmentation fault from the dialplan.
583 + * (I know what you are thinking now...., but since Asterisk is too stable...
584 + * I needed something to test my failover switches.)
586 + * Copyright (C) 2005 Junghanns.NET GmbH
587 + * Klaus-Peter Junghanns <kpj@junghanns.net>
589 + * This program is free software, distributed under the terms of
590 + * the GNU General Public License. THIS APPLICATION _WILL_ CRASH YOUR
591 + * ASTERISK SERVER SO OF COURSE THERE IS NOT LIABILITY FOR NOTHING!
594 +#include "asterisk.h"
600 +#include <asterisk/lock.h>
601 +#include <asterisk/file.h>
602 +#include <asterisk/logger.h>
603 +#include <asterisk/channel.h>
604 +#include <asterisk/pbx.h>
605 +#include <asterisk/module.h>
607 +static char *app = "Segfault";
609 +static char *synopsis = "This application will crash Asterisk with a segmentation fault.";
611 +static char *descrip =
612 +" Segfault(): Crash with a segfault. Never returns nufin.\n";
614 +static int segfault_exec(struct ast_channel *chan, void *data)
616 + ((char *)0)[0] = 0;
620 +static int unload_module(void)
622 + return ast_unregister_application(app);
625 +static int load_module(void)
627 + return ast_register_application(app, segfault_exec, synopsis, descrip);
630 +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Application for crashing Asterisk with a segmentation fault",
631 + .load = load_module,
632 + .unload = unload_module,
634 --- a/apps/app_directed_pickup.c
635 +++ b/apps/app_directed_pickup.c
636 @@ -45,7 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
638 #define PICKUPMARK "PICKUPMARK"
640 -static const char *app = "Pickup";
641 +static const char *app = "DPickup";
642 static const char *synopsis = "Directed Call Pickup";
643 static const char *descrip =
644 " Pickup(extension[@context][&extension2@context...]): This application can pickup any ringing channel\n"
646 +++ b/apps/app_pickup.c
649 + * Asterisk -- A telephony toolkit for Linux.
651 + * Pickup, channel independent call pickup
653 + * Copyright (C) 2004, Junghanns.NET GmbH
655 + * Klaus-Peter Junghanns <kpj@junghanns.net>
657 + * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
659 + * This program is free software, distributed under the terms of
660 + * the GNU General Public License
663 +#include "asterisk.h"
670 +#include <pthread.h>
671 +#include <asterisk/lock.h>
672 +#include <asterisk/file.h>
673 +#include <asterisk/logger.h>
674 +#include <asterisk/channel.h>
675 +#include <asterisk/pbx.h>
676 +#include <asterisk/module.h>
677 +#include <asterisk/features.h>
678 +#include <asterisk/options.h>
681 +static char *app = "PickUp";
683 +static char *synopsis = "Channel independent call pickup.";
685 +static char *descrip =
686 +" PickDown([group]): Tries to pickup the first ringing channel with callgroup == group.\n"
687 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
689 +static char *app2 = "Steal";
691 +static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
693 +static char *descrip2 =
694 +" Steal([group]): Tries to steal the first bridged channel with callgroup == group.\n"
695 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
697 +static char *app3 = "PickDown";
699 +static char *synopsis3 = "Channel independent call pickdown.";
701 +static char *descrip3 =
702 +" PickDown([group]): Tries to hangup the first ringing channel with callgroup == group.\n"
703 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
705 +static char *app4 = "PickupChan";
707 +static char *synopsis4 = "Channel independent call pickup.";
709 +static char *descrip4 =
710 +" PickupChan(Technology/resource[&Technology2/resource2...]): Tries to pickup the first ringing channel in the parameter list.\n";
712 +static char *app5 = "StealChan";
714 +static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
716 +static char *descrip5 =
717 +" StealChan(Technology/resource[&Technology2/resource2...]): Tries to steal the first ringing channel in the parameter list.\n";
720 +static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
721 + struct ast_channel *cur;
723 + cur = ast_channel_walk_locked(NULL);
725 + if ((cur != chan) &&
726 + (pickupgroup & cur->callgroup) &&
727 + (cur->_state == chanstate)) {
730 + ast_mutex_unlock(&cur->lock);
731 + cur = ast_channel_walk_locked(cur);
734 + if(option_verbose > 2) {
735 + if (chanstate == AST_STATE_RINGING) {
737 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
739 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
742 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
746 + if (chan->_state != AST_STATE_UP) {
749 + if (ast_channel_masquerade(cur, chan)) {
750 + ast_log(LOG_ERROR, "unable to masquerade\n");
752 + ast_mutex_unlock(&cur->lock);
753 + ast_mutex_unlock(&chan->lock);
755 + cur->_softhangup = AST_SOFTHANGUP_DEV;
756 + ast_mutex_unlock(&cur->lock);
759 + if(option_verbose > 2) {
760 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
766 +static int my_pickup_channel(struct ast_channel *chan, void *data, int chanstate, int bridge) {
767 + struct ast_channel *cur;
768 + char channels[256];
769 + char evalchan[256];
772 + cur = ast_channel_walk_locked(NULL);
773 + strncpy(channels, (char *)data, sizeof(channels) - 1);
775 + if ((cur != chan) &&
776 + (cur->_state == chanstate)) {
777 + /* This call is a candidate (correct ringstate and not ourselves), now check if the channel is in our list */
778 + strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);
779 + /* strip the subchannel tag */
780 + endptr = strrchr(evalchan, '-');
784 + /* check for each of the members if they match (probably a stristr will do ?) */
785 + /* if we match the code, break */
786 + if(strstr(channels, evalchan) != NULL) {
787 + ast_verbose(VERBOSE_PREFIX_1 "Nice channel, I'll take it: %s\n",evalchan);
791 + ast_mutex_unlock(&cur->lock);
792 + cur = ast_channel_walk_locked(cur);
795 + if(option_verbose > 2) {
796 + if (chanstate == AST_STATE_RINGING) {
798 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
800 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
803 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
807 + if (chan->_state != AST_STATE_UP) {
810 + if (ast_channel_masquerade(cur, chan)) {
811 + ast_log(LOG_ERROR, "unable to masquerade\n");
813 + ast_mutex_unlock(&cur->lock);
814 + ast_mutex_unlock(&chan->lock);
816 + cur->_softhangup = AST_SOFTHANGUP_DEV;
817 + ast_mutex_unlock(&cur->lock);
820 + if(option_verbose > 2) {
821 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
828 +static int pickup_exec(struct ast_channel *chan, void *data)
831 + unsigned int pickupgroup=0;
832 + struct ast_module_user *u;
833 + if (!data || !strlen(data)) {
834 + pickupgroup = chan->pickupgroup;
836 + pickupgroup = ast_get_group(data);
838 + u = ast_module_user_add(chan);
840 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
844 + ast_module_user_remove(u);
848 +static int steal_exec(struct ast_channel *chan, void *data)
851 + unsigned int pickupgroup=0;
852 + struct ast_module_user *u;
853 + if (!data || !strlen(data)) {
854 + pickupgroup = chan->pickupgroup;
856 + pickupgroup = ast_get_group(data);
858 + u = ast_module_user_add(chan);
860 + res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
864 + ast_module_user_remove(u);
868 +static int pickdown_exec(struct ast_channel *chan, void *data)
871 + unsigned int pickupgroup=0;
872 + struct ast_module_user *u;
873 + if (!data || !strlen(data)) {
874 + pickupgroup = chan->pickupgroup;
876 + pickupgroup = ast_get_group(data);
878 + u = ast_module_user_add(chan);
880 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
884 + ast_module_user_remove(u);
888 +static int pickupchan_exec(struct ast_channel *chan, void *data) {
890 + struct ast_module_user *u;
892 + ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
895 + u = ast_module_user_add(chan);
897 + res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
901 + ast_module_user_remove(u);
905 +static int stealchan_exec(struct ast_channel *chan, void *data)
908 + struct ast_module_user *u;
910 + ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
914 + u = ast_module_user_add(chan);
916 + res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
920 + ast_module_user_remove(u);
925 +static int unload_module(void)
927 + ast_module_user_hangup_all();
928 + ast_unregister_application(app5);
929 + ast_unregister_application(app4);
930 + ast_unregister_application(app3);
931 + ast_unregister_application(app2);
932 + return ast_unregister_application(app);
935 +static int load_module(void)
937 + ast_register_application(app5, stealchan_exec, synopsis5, descrip5);
938 + ast_register_application(app4, pickupchan_exec, synopsis4, descrip4);
939 + ast_register_application(app3, pickdown_exec, synopsis3, descrip3);
940 + ast_register_application(app2, steal_exec, synopsis2, descrip2);
941 + return ast_register_application(app, pickup_exec, synopsis, descrip);
944 +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PickUp/PickDown/Steal/PickupChan/StealChan",
945 + .load = load_module,
946 + .unload = unload_module,
949 +++ b/apps/app_devstate.c
952 + * Devstate application
954 + * Since we like the snom leds so much, a little app to
955 + * light the lights on the snom on demand ....
957 + * Copyright (C) 2005, Druid Software
959 + * This program is free software, distributed under the terms of
960 + * the GNU General Public License
963 +#include "asterisk.h"
970 +#include "asterisk/lock.h"
971 +#include "asterisk/file.h"
972 +#include "asterisk/logger.h"
973 +#include "asterisk/channel.h"
974 +#include "asterisk/pbx.h"
975 +#include "asterisk/astdb.h"
976 +#include "asterisk/cli.h"
977 +#include "asterisk/manager.h"
978 +#include "asterisk/devicestate.h"
979 +#include "asterisk/module.h"
982 +static char type[] = "DS";
983 +static char tdesc[] = "Application for sending device state messages";
985 +static char app[] = "Devstate";
987 +static char synopsis[] = "Generate a device state change event given the input parameters";
989 +static char descrip[] = " Devstate(device|state): Generate a device state change event given the input parameters. Returns 0. State values match the asterisk device states. They are 0 = unknown, 1 = not inuse, 2 = inuse, 3 = busy, 4 = invalid, 5 = unavailable, 6 = ringing\n";
991 +static char devstate_cli_usage[] =
992 +"Usage: devstate device state\n"
993 +" Generate a device state change event given the input parameters.\n Mainly used for lighting the LEDs on the snoms.\n";
995 +static int devstate_cli(int fd, int argc, char *argv[]);
996 +static struct ast_cli_entry cli_dev_state =
997 + { { "devstate", NULL }, devstate_cli, "Set the device state on one of the \"pseudo devices\".", devstate_cli_usage };
1000 +static int devstate_cli(int fd, int argc, char *argv[])
1002 + char devName[128];
1004 + return RESULT_SHOWUSAGE;
1006 + if (ast_db_put("DEVSTATES", argv[1], argv[2]))
1008 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1010 + snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
1011 + ast_device_state_changed_literal(devName);
1012 + return RESULT_SUCCESS;
1015 +static int devstate_exec(struct ast_channel *chan, void *data)
1017 + char *device, *state, *info;
1018 + char devName[128];
1019 + struct ast_module_user *u;
1022 + if (!(info = ast_strdupa(data))) {
1023 + ast_log(LOG_WARNING, "Unable to dupe data :(\n");
1027 + u = ast_module_user_add(chan);
1029 + state = strchr(info, '|');
1036 + ast_log(LOG_DEBUG, "No state argument supplied\n");
1040 + if (ast_db_put("DEVSTATES", device, state))
1042 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1045 + snprintf(devName, sizeof(devName), "DS/%s", device);
1046 + ast_device_state_changed_literal(devName);
1048 + ast_module_user_remove(u);
1053 +static int ds_devicestate(void *data)
1055 + char *dest = data;
1056 + char stateStr[16];
1057 + if (ast_db_get("DEVSTATES", dest, stateStr, sizeof(stateStr)))
1059 + ast_log(LOG_DEBUG, "ds_devicestate couldnt get state in astdb\n");
1064 + ast_log(LOG_DEBUG, "ds_devicestate dev=%s returning state %d\n",
1065 + dest, atoi(stateStr));
1066 + return (atoi(stateStr));
1070 +static struct ast_channel_tech devstate_tech = {
1072 + .description = tdesc,
1073 + .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
1074 + .devicestate = ds_devicestate,
1075 + .requester = NULL,
1076 + .send_digit_begin = NULL,
1077 + .send_digit_end = NULL,
1078 + .send_text = NULL,
1085 + .exception = NULL,
1088 + .setoption = NULL,
1091 +static char mandescr_devstate[] =
1092 +"Description: Put a value into astdb\n"
1098 +static int action_devstate(struct mansession *s, const struct message *m)
1100 + const char *devstate = astman_get_header(m, "Devstate");
1101 + const char *value = astman_get_header(m, "Value");
1102 + const char *id = astman_get_header(m,"ActionID");
1103 + char devName[128];
1104 + char idText[256] = "";
1106 + if (!strlen(devstate)) {
1107 + astman_send_error(s, m, "No Devstate specified");
1110 + if (!strlen(value)) {
1111 + astman_send_error(s, m, "No Value specified");
1114 + if (!ast_strlen_zero(id))
1115 + snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
1117 + if (!ast_db_put("DEVSTATES", devstate, (char *)value)) {
1118 + snprintf(devName, sizeof(devName), "DS/%s", devstate);
1119 + ast_device_state_changed_literal(devName);
1120 + astman_append(s, "Response: Success\r\n%s\r\n", idText);
1122 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1123 + astman_append(s, "Response: Failed\r\n%s\r\n", idText);
1128 +static int load_module(void)
1130 + if (ast_channel_register(&devstate_tech)) {
1131 + ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
1134 + ast_cli_register(&cli_dev_state);
1135 + ast_manager_register2( "Devstate", EVENT_FLAG_CALL, action_devstate, "Change a device state", mandescr_devstate );
1136 + return ast_register_application(app, devstate_exec, synopsis, descrip);
1139 +static int unload_module(void)
1143 + ast_module_user_hangup_all();
1144 + ast_manager_unregister( "Devstate");
1145 + ast_cli_unregister(&cli_dev_state);
1146 + res = ast_unregister_application(app);
1147 + ast_channel_unregister(&devstate_tech);
1151 +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Devstate Application");
1154 +++ b/configs/watchdog.conf.sample
1157 +; Configuration file for res_watchdog
1159 +; type = isdnguard | watchdog
1160 +; device = /dev/...
1161 +; interval = interval to trigger the watchdog in ms
1163 +;[ISDNguard-direct]
1165 +;device = /dev/ttyS0
1168 +;[ISDNguard-with-daemon]
1170 +;device = /var/run/guard.ctl
1175 +;device = /dev/watchdog
1179 +++ b/res/res_watchdog.c
1182 + * Asterisk -- A telephony toolkit for Linux.
1184 + * Resource to make watchdogs happy
1186 + * Copyright (C) 2005, Junghanns.NET GmbH
1188 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1190 + * This program is free software, distributed under the terms of
1191 + * the GNU General Public License
1194 +#include "asterisk.h"
1195 +#include <stdlib.h>
1197 +#include <unistd.h>
1198 +#include <string.h>
1199 +#include <stdlib.h>
1201 +#include <sys/time.h>
1202 +#include <sys/signal.h>
1203 +#include <netinet/in.h>
1205 +#include <asterisk/logger.h>
1206 +#include <asterisk/channel.h>
1207 +#include <asterisk/pbx.h>
1208 +#include <asterisk/options.h>
1209 +#include <asterisk/module.h>
1210 +#include <asterisk/translate.h>
1211 +#include <asterisk/say.h>
1212 +#include <asterisk/features.h>
1213 +#include <asterisk/musiconhold.h>
1214 +#include <asterisk/config.h>
1215 +#include <asterisk/cli.h>
1216 +#include <asterisk/manager.h>
1217 +#include <asterisk/utils.h>
1218 +#include <asterisk/lock.h>
1219 +#include <asterisk/adsi.h>
1221 +static struct watchdog_pvt *watchdogs = NULL;
1223 +typedef struct watchdog_pvt {
1228 + pthread_t watchdog_thread;
1229 + struct watchdog_pvt *next;
1232 +static void *do_watchdog_thread(void *data) {
1233 + struct watchdog_pvt *woof = (struct watchdog_pvt *)data;
1236 + write(woof->fd, "PING\n", 5);
1238 + usleep(woof->interval * 1000);
1244 +static int load_module(void)
1247 + const char *cat, *utype, *udevice, *uinterval;
1248 + struct ast_config *cfg;
1249 + struct watchdog_pvt *woof = NULL;
1251 + cfg = ast_config_load("watchdog.conf");
1253 + cat = ast_category_browse(cfg, NULL);
1255 + cat = ast_category_browse(cfg, cat);
1256 + utype = ast_variable_retrieve(cfg, cat, "type");
1258 + ast_log(LOG_NOTICE, "type = %s\n", utype);
1260 + udevice = ast_variable_retrieve(cfg, cat, "device");
1262 + ast_log(LOG_NOTICE, "device = %s\n", udevice);
1264 + uinterval = ast_variable_retrieve(cfg, cat, "interval");
1265 +/* if (uinterval) {
1266 + ast_log(LOG_NOTICE, "interval = %s\n", uinterval);
1268 + if (uinterval && udevice && utype) {
1269 + woof = malloc(sizeof(struct watchdog_pvt));
1271 + ast_log(LOG_ERROR, "unable to malloc!\n");
1274 + memset(woof, 0x0, sizeof(struct watchdog_pvt));
1275 + strncpy(woof->device, udevice, sizeof(woof->device) - 1);
1277 + woof->interval = atoi(uinterval);;
1278 + woof->next = watchdogs;
1280 + woof->fd = open(woof->device, O_WRONLY | O_SYNC);
1282 + if (!strncmp(utype, "isdnguard", sizeof(utype))) {
1284 + write(woof->fd, "START\n", 6);
1286 + ast_pthread_create(&woof->watchdog_thread, NULL, do_watchdog_thread, woof);
1288 + ast_log(LOG_WARNING, "error opening watchdog device %s !\n", woof->device);
1292 + ast_config_destroy(cfg);
1298 +static int unload_module(void)
1300 + struct watchdog_pvt *dogs, *woof;
1303 + pthread_cancel(dogs->watchdog_thread);
1304 + pthread_join(dogs->watchdog_thread, NULL);
1306 + woof = dogs->next;
1314 +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Watchdog Resource",
1315 + .load = load_module,
1316 + .unload = unload_module,
1320 @@ -574,7 +574,7 @@ static int manager_dbget(struct mansessi
1321 astman_append(s, "Event: DBGetResponse\r\n"
1328 family, key, tmp, idText);
1329 @@ -582,11 +582,35 @@ static int manager_dbget(struct mansessi
1333 +static int manager_dbdel(struct mansession *s, const struct message *m)
1335 + const char *family = astman_get_header(m, "Family");
1336 + const char *key = astman_get_header(m, "Key");
1338 + if (!strlen(family)) {
1339 + astman_send_error(s, m, "No family specified");
1342 + if (!strlen(key)) {
1343 + astman_send_error(s, m, "No key specified");
1347 + if (ast_db_del(family, key)) {
1348 + astman_send_error(s, m, "Failed to delete entry");
1350 + astman_send_ack(s, m, "Deleted entry successfully");
1356 int astdb_init(void)
1359 ast_cli_register_multiple(cli_database, sizeof(cli_database) / sizeof(struct ast_cli_entry));
1360 - ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
1361 - ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
1362 + ast_manager_register("DBget", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
1363 + ast_manager_register("DBput", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
1364 + ast_manager_register("DBdel", EVENT_FLAG_SYSTEM, manager_dbdel, "Delete DB Entry");
1368 +++ b/configs/esel.conf.sample
1371 +; Configuration file for res_esel
1375 +;host = 192.168.0.1
1377 +;username = manager
1380 +; export the extension snom in context phones to DS/100
1381 +;export => snom@phones,100
1383 +++ b/res/res_esel.c
1386 + * Asterisk -- A telephony toolkit for Linux.
1388 + * Extension State Export Logic (E.S.E.L) (Sorry, i couldnt resist...)
1390 + * Resource to export extension states to other Asterisk servers
1392 + * Copyright (C) 2006, Junghanns.NET GmbH
1394 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1396 + * This program is free software, distributed under the terms of
1397 + * the GNU General Public License
1400 +#include "asterisk.h"
1402 +#include <stdlib.h>
1404 +#include <unistd.h>
1405 +#include <string.h>
1406 +#include <stdlib.h>
1408 +#include <sys/time.h>
1409 +#include <sys/signal.h>
1410 +#include <netinet/in.h>
1411 +#include <sys/types.h>
1412 +#include <sys/socket.h>
1414 +#include "asterisk/file.h"
1415 +#include "asterisk/logger.h"
1416 +#include "asterisk/channel.h"
1417 +#include "asterisk/pbx.h"
1418 +#include "asterisk/options.h"
1419 +#include "asterisk/module.h"
1420 +#include "asterisk/translate.h"
1421 +#include "asterisk/say.h"
1422 +#include "asterisk/features.h"
1423 +#include "asterisk/musiconhold.h"
1424 +#include "asterisk/config.h"
1425 +#include "asterisk/cli.h"
1426 +#include "asterisk/manager.h"
1427 +#include "asterisk/utils.h"
1428 +#include "asterisk/lock.h"
1429 +#include "asterisk/adsi.h"
1432 +AST_MUTEX_DEFINE_STATIC(listlock);
1434 +typedef struct esel_extension_state {
1435 + char context[AST_MAX_EXTENSION];
1436 + char exten[AST_MAX_EXTENSION];
1438 + char devstate[AST_MAX_EXTENSION];
1439 + struct esel_extension_state *next;
1440 + struct esel_extension_state *prev;
1441 +} esel_extension_state;
1443 +typedef struct esel_export {
1444 + char context[AST_MAX_EXTENSION];
1445 + char exten[AST_MAX_EXTENSION];
1446 + char devstate[AST_MAX_EXTENSION];
1447 + struct esel_export *next;
1450 +typedef struct esel_queue {
1451 + struct esel_extension_state *head;
1452 + struct esel_extension_state *tail;
1458 +typedef struct esel_pvt {
1460 + char username[80];
1464 + struct sockaddr_in raddr;
1467 + pthread_t esel_thread;
1469 + /* list of extensions to export */
1470 + struct esel_export *extensions;
1473 + struct esel_queue queue;
1475 + struct esel_pvt *next;
1478 +static struct esel_pvt *donkeys = NULL;
1480 +static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data) {
1481 + struct esel_extension_state *exstate = NULL;
1483 + exstate = malloc(sizeof(struct esel_extension_state));
1485 + ast_log(LOG_ERROR, "Unable to malloc!\n");
1488 + memset(exstate,0,sizeof(struct esel_extension_state));
1489 + exstate->next = NULL;
1490 + exstate->prev = NULL;
1492 + ast_mutex_lock(&queue->lock);
1493 + if (queue->count > 100) {
1494 + ast_mutex_unlock(&queue->lock);
1496 + if (option_verbose > 5)
1497 + ast_log(LOG_WARNING, "E.S.E.L Queue too long.\n");
1500 + ast_copy_string(exstate->exten, exten, sizeof(exstate->exten));
1501 + ast_copy_string(exstate->context, context, sizeof(exstate->context));
1502 + exstate->state = state;
1503 + if (!queue->head) {
1505 + queue->head = exstate;
1506 + queue->tail = exstate;
1509 + queue->tail->next = exstate;
1510 + exstate->prev = queue->tail;
1511 + queue->tail = exstate;
1514 + ast_cond_signal(&queue->cond);
1515 + ast_mutex_unlock(&queue->lock);
1519 +static int esel_is_exported(struct esel_export *extensions, struct esel_extension_state *exstate) {
1520 + struct esel_export *export = NULL;
1521 + export = extensions;
1523 + if ((!strcasecmp(export->exten, exstate->exten)) && (!strcasecmp(export->context, exstate->context))) {
1524 + /* copy mapping */
1525 + ast_copy_string(exstate->devstate, export->devstate, sizeof(exstate->devstate));
1528 + export = export->next;
1533 +static int esel_state2devstate(int state) {
1544 +static void esel_export_to_remote(struct esel_extension_state *exstate, struct esel_pvt *esel) {
1547 + memset(msg, 0x0, sizeof(msg));
1548 + snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state));
1549 + sent = send(esel->sockfd, msg, strlen(msg), 0);
1551 + esel->connected = 0;
1553 +// ast_log(LOG_NOTICE, "%s", msg);
1556 +static void *do_esel_thread(void *data) {
1557 + struct esel_pvt *esel = (struct esel_pvt *)data;
1558 + struct esel_queue *queue = &esel->queue;
1559 + struct esel_extension_state *exstate = NULL;
1566 + if (esel->connected) {
1567 + ast_mutex_lock(&queue->lock);
1568 + if (queue->count == 0)
1569 + ast_cond_wait(&queue->cond, &queue->lock);
1570 + exstate = queue->head;
1572 + if (exstate->next) {
1573 + queue->head = exstate->next;
1575 + queue->head = NULL;
1576 + queue->tail = NULL;
1580 + ast_log(LOG_ERROR, "I SHOULD NEVER HAPPEN! EXPECT SOME MAJOR KABOOM! DUCK AND COVER!\n");
1582 + ast_mutex_unlock(&queue->lock);
1585 + if (esel_is_exported(esel->extensions, exstate)) {
1586 + esel_export_to_remote(exstate, esel);
1592 + if (esel->sockfd > 0)
1593 + close(esel->sockfd);
1594 + if ((esel->sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
1595 + ast_log(LOG_ERROR, "unable to request socket!\n");
1598 + /* try to connect */
1599 + res = connect(esel->sockfd, (struct sockaddr *)&esel->raddr, sizeof(struct sockaddr));
1601 + ast_log(LOG_NOTICE, "error connecting to %s:%d\n", esel->host, esel->port);
1603 + while (strncasecmp(buf, "Asterisk Call Manager:", 21)) {
1604 + if ((numbytes=recv(esel->sockfd, buf, sizeof(buf), 0)) == -1) {
1605 + esel->connected = 0;
1608 + buf[numbytes] = '\0';
1609 + // ast_log(LOG_NOTICE, "read: %s", buf);
1611 + /* log into remote manager */
1612 + memset(msg, 0x0, sizeof(msg));
1613 + snprintf(msg, sizeof(msg) - 1, "Action: Login\r\nUsername: %s\r\nSecret: %s\r\n\r\n", esel->username, esel->secret);
1614 + sent = send(esel->sockfd, msg, strlen(msg), 0);
1616 + while (strncasecmp(buf, "Response:", 9)) {
1617 + if ((numbytes=recv(esel->sockfd, buf, sizeof(buf), 0)) == -1) {
1620 + buf[numbytes] = '\0';
1621 + // ast_log(LOG_NOTICE, "read: %s", buf);
1624 + if (!strncasecmp(buf, "Response: Success", 17)) {
1625 + esel->connected = 1;
1627 + ast_log(LOG_ERROR, "error login into remote asterisk %s\n", esel->name);
1630 + /* time heals everything... */
1637 +static int esel_state_cb(char *context, char *exten, int state, void *data) {
1638 + struct esel_pvt *esel;
1641 + ast_mutex_lock(&listlock);
1643 + esel_queue_extension_state(&esel->queue, context, exten, state, data);
1644 + esel = esel->next;
1646 + ast_mutex_unlock(&listlock);
1651 +static int load_module(void)
1654 + const char *cat, *host, *port, *username, *secret, *name;
1655 + struct ast_config *cfg;
1656 + struct ast_variable *var;
1657 + struct esel_pvt *esel = NULL;
1658 + struct esel_export *export = NULL;
1659 + struct hostent *he;
1660 + struct ast_hostent h;
1662 + cfg = ast_config_load("esel.conf");
1664 + cat = ast_category_browse(cfg, NULL);
1667 + host = ast_variable_retrieve(cfg, cat, "host");
1668 + username = ast_variable_retrieve(cfg, cat, "username");
1669 + secret = ast_variable_retrieve(cfg, cat, "secret");
1670 + port = ast_variable_retrieve(cfg, cat, "port");
1672 + if (name && host && username && secret && port) {
1673 + esel = malloc(sizeof(struct esel_pvt));
1675 + ast_log(LOG_ERROR, "unable to malloc!\n");
1678 + memset(esel, 0x0, sizeof(struct esel_pvt));
1679 + ast_copy_string(esel->name, name, sizeof(esel->name));
1680 + ast_copy_string(esel->host, host, sizeof(esel->host));
1681 + ast_copy_string(esel->username, username, sizeof(esel->username));
1682 + ast_copy_string(esel->secret, secret, sizeof(esel->secret));
1684 + esel->port = atoi(port);
1685 + if ((he=ast_gethostbyname(host, &h)) == NULL) {
1686 + ast_log(LOG_ERROR, "unknown host!\n");
1690 + esel->raddr.sin_family = AF_INET;
1691 + esel->raddr.sin_port = htons(esel->port);
1692 + esel->raddr.sin_addr = *((struct in_addr *)he->h_addr);
1693 + bzero(&(esel->raddr.sin_zero), 8);
1695 + esel->connected = 0;
1697 + ast_mutex_init(&esel->queue.lock);
1698 + ast_cond_init(&esel->queue.cond, NULL);
1701 + /* read exports */
1702 + var = ast_variable_browse(cfg, cat);
1704 + if (!strcasecmp(var->name, "export")) {
1705 + char *extenp = NULL, *contextp = NULL, *devstatep = NULL;
1706 + extenp = var->value;
1707 + devstatep = strchr(var->value, ',') + 1;
1708 + contextp = strchr(var->value, '@') + 1;
1709 + if (devstatep && contextp) {
1710 + export = malloc(sizeof(struct esel_export));
1712 + ast_log(LOG_ERROR, "unable to malloc!\n");
1715 + memset(export, 0x0, sizeof(struct esel_export));
1716 + ast_copy_string(export->exten, extenp, contextp - extenp);
1717 + ast_copy_string(export->context, contextp, devstatep - contextp);
1718 + ast_copy_string(export->devstate, devstatep, sizeof(export->devstate));
1719 + if (option_verbose > 2)
1720 + ast_verbose(VERBOSE_PREFIX_3 "exporting %s @ %s as %s to %s\n", export->exten, export->context , export->devstate , esel->name);
1721 + export->next = esel->extensions;
1722 + esel->extensions = export;
1731 + esel->next = donkeys;
1734 + ast_pthread_create(&esel->esel_thread, NULL, do_esel_thread, esel);
1737 + cat = ast_category_browse(cfg, cat);
1739 + ast_config_destroy(cfg);
1741 + ast_extension_state_add(NULL, NULL, esel_state_cb, NULL);
1746 +static int unload_module(void)
1748 + struct esel_pvt *esel, *eseln;
1749 + ast_module_user_hangup_all();
1751 + ast_mutex_lock(&listlock);
1753 + pthread_cancel(esel->esel_thread);
1754 + pthread_join(esel->esel_thread, NULL);
1755 + ast_mutex_destroy(&esel->queue.lock);
1756 + close(esel->sockfd);
1757 + eseln = esel->next;
1761 + ast_mutex_unlock(&listlock);
1765 +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Extension State Export Logic (E.S.E.L.) Resource",
1766 + .load = load_module,
1767 + .unload = unload_module,
1769 --- a/channels/chan_iax2.c
1770 +++ b/channels/chan_iax2.c
1772 * the project provides a web site, mailing lists and IRC
1773 * channels for your use.
1775 + * Hangup cause signalling implementation by
1776 + * Levent Guendogdu <levon@feature-it.com>
1778 * This program is free software, distributed under the terms of
1779 * the GNU General Public License Version 2. See the LICENSE file
1780 * at the top of the source tree.
1781 @@ -3362,7 +3365,7 @@ static int iax2_hangup(struct ast_channe
1782 ast_mutex_lock(&iaxsl[callno]);
1783 if (callno && iaxs[callno]) {
1785 - ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
1786 + ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
1787 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
1788 /* Send the hangup unless we have had a transmission error or are already gone */
1789 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
1790 @@ -3416,7 +3419,8 @@ static int iax2_setoption(struct ast_cha
1792 static struct ast_frame *iax2_read(struct ast_channel *c)
1794 - ast_log(LOG_NOTICE, "I should never be called!\n");
1795 + if (option_verbose > 3)
1796 + ast_log(LOG_NOTICE, "I should never be called!\n");
1797 return &ast_null_frame;
1800 --- a/apps/app_zapras.c
1801 +++ b/apps/app_zapras.c
1802 @@ -183,7 +183,7 @@ static void run_ras(struct ast_channel *
1805 /* Throw back into audio mode */
1808 ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
1810 /* Restore saved values */
1811 --- a/main/channel.c
1812 +++ b/main/channel.c
1813 @@ -3898,6 +3898,10 @@ enum ast_bridge_result ast_channel_bridg
1814 c1->name, c1->_bridge->name);
1818 + if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
1819 + config->flags = 0;
1822 /* Stop if we're a zombie or need a soft hangup */
1823 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
1824 --- a/apps/app_meetme.c
1825 +++ b/apps/app_meetme.c
1826 @@ -1405,8 +1405,9 @@ static int conf_run(struct ast_channel *
1827 char members[10] = "";
1828 int dtmf, opt_waitmarked_timeout = 0;
1830 + int dyna_buff = CONF_SIZE;
1832 - char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
1833 + char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET];
1834 char *buf = __buf + AST_FRIENDLY_OFFSET;
1835 int setusercount = 0;
1837 @@ -1615,7 +1616,7 @@ static int conf_run(struct ast_channel *
1839 /* Setup buffering information */
1840 memset(&bi, 0, sizeof(bi));
1841 - bi.bufsize = CONF_SIZE/2;
1842 + bi.bufsize = dyna_buff / 2;
1843 bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
1844 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
1845 bi.numbufs = audio_buffers;
1846 @@ -1926,6 +1927,14 @@ static int conf_run(struct ast_channel *
1850 + if (f->datalen && f->datalen != dyna_buff) {
1851 + ast_log(LOG_NOTICE, "Audio bytes: %d Buffer size: %d\n", f->datalen, dyna_buff);
1852 + if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */
1853 + dyna_buff = f->datalen;
1858 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
1859 if (user->talk.actual)
1860 ast_frame_adjust_volume(f, user->talk.actual);
1861 Answer the channel before saying things (SayNumber, SayDigits,
1862 SayCharacters, SayPhonetic).
1866 @@ -6076,6 +6076,9 @@ static int pbx_builtin_saynumber(struct
1870 + if (chan->_state != AST_STATE_UP) {
1874 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
1875 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
1876 @@ -6088,8 +6091,12 @@ static int pbx_builtin_saydigits(struct
1882 + if (chan->_state != AST_STATE_UP) {
1885 res = ast_say_digit_str(chan, data, "", chan->language);
1890 @@ -6097,8 +6104,12 @@ static int pbx_builtin_saycharacters(str
1896 + if (chan->_state != AST_STATE_UP) {
1899 res = ast_say_character_str(chan, data, "", chan->language);
1904 @@ -6106,8 +6117,12 @@ static int pbx_builtin_sayphonetic(struc
1910 + if (chan->_state != AST_STATE_UP) {
1913 res = ast_say_phonetic_str(chan, data, "", chan->language);
1918 --- a/apps/app_dial.c
1919 +++ b/apps/app_dial.c
1921 * the project provides a web site, mailing lists and IRC
1922 * channels for your use.
1924 + * Copyright (C) 2004, Junghanns.NET GmbH
1926 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1928 * This program is free software, distributed under the terms of
1929 * the GNU General Public License Version 2. See the LICENSE file
1930 * at the top of the source tree.
1931 @@ -130,7 +134,8 @@ static char *descrip =
1932 " H - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
1933 " i - Asterisk will ignore any forwarding requests it may receive on this\n"
1935 -" j - Jump to priority n+101 if all of the requested channels were busy.\n"
1936 +" j - Jump to priority n+101 if the called party was busy.\n"
1937 +" Jump to priority n+201 if all of the requested channels were busy.\n"
1938 " k - Allow the called party to enable parking of the call by sending\n"
1939 " the DTMF sequence defined for call parking in features.conf.\n"
1940 " K - Allow the calling party to enable parking of the call by sending\n"
1941 @@ -1292,14 +1297,16 @@ static int dial_exec_full(struct ast_cha
1945 - strcpy(status, "CHANUNAVAIL");
1946 + ast_copy_string(status, "CHANUNAVAIL", sizeof(status));
1947 if(fulldial == num_dialed) {
1951 + /* See if there is a special message */
1952 + ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1954 /* Our status will at least be NOANSWER */
1955 - strcpy(status, "NOANSWER");
1956 + ast_copy_string(status, "NOANSWER", sizeof(status));
1957 if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
1959 if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
1960 --- a/apps/app_dial.c
1961 +++ b/apps/app_dial.c
1962 @@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
1963 #include "asterisk/privacy.h"
1964 #include "asterisk/stringfields.h"
1965 #include "asterisk/global_datastores.h"
1966 +#include "asterisk/transcap.h"
1968 static char *app = "Dial";
1970 @@ -1652,23 +1653,25 @@ static int dial_exec_full(struct ast_cha
1971 ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
1973 ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
1974 - if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1975 + if ((chan->transfercapability != AST_TRANS_CAP_DIGITAL) && (chan->transfercapability != AST_TRANS_CAP_RESTRICTED_DIGITAL)) {
1976 + /* only non-digital calls are allowed to go through userspace */
1977 + if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1978 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1979 - if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1980 + if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1981 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1982 - if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1983 + if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1984 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1985 - if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1986 + if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1987 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1988 - if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1989 + if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1990 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1991 - if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
1992 + if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
1993 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1994 - if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
1995 + if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
1996 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
1997 - if (ast_test_flag(peerflags, OPT_CALLER_PARK))
1998 + if (ast_test_flag(peerflags, OPT_CALLER_PARK))
1999 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2002 config.timelimit = timelimit;
2003 config.play_warning = play_warning;
2004 config.warning_freq = warning_freq;
2005 --- a/apps/app_dial.c
2006 +++ b/apps/app_dial.c
2007 @@ -198,6 +198,8 @@ static char *descrip =
2008 " family/key is not specified.\n"
2009 " r - Indicate ringing to the calling party. Pass no audio to the calling\n"
2010 " party until the called channel has answered.\n"
2011 +" R - indicate ringing to the calling party when the called party indicates\n"
2012 +" ringing, pass no audio until answered.\n"
2013 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
2014 " answered the call.\n"
2015 " t - Allow the called party to transfer the calling party by sending the\n"
2016 @@ -254,6 +256,7 @@ enum {
2017 OPT_CALLEE_PARK = (1 << 25),
2018 OPT_CALLER_PARK = (1 << 26),
2019 OPT_IGNORE_FORWARDING = (1 << 27),
2020 + OPT_NOINBAND = (1 << 28),
2021 } dial_exec_option_flags;
2023 #define DIAL_STILLGOING (1 << 30)
2024 @@ -297,6 +300,7 @@ AST_APP_OPTIONS(dial_exec_options, {
2025 AST_APP_OPTION('p', OPT_SCREENING),
2026 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
2027 AST_APP_OPTION('r', OPT_RINGBACK),
2028 + AST_APP_OPTION('R', OPT_NOINBAND),
2029 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
2030 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
2031 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
2032 @@ -412,7 +416,7 @@ static struct ast_channel *wait_for_answ
2034 struct ast_channel *peer = NULL;
2035 /* single is set if only one destination is enabled */
2036 - int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
2037 + int single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_NOINBAND));
2040 /* Turn off hold music, etc */
2041 @@ -633,7 +637,7 @@ static struct ast_channel *wait_for_answ
2042 /* Setup early media if appropriate */
2043 if (single && CAN_EARLY_BRIDGE(peerflags))
2044 ast_rtp_early_bridge(in, c);
2045 - if (!ast_test_flag(outgoing, OPT_RINGBACK))
2046 + if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_NOINBAND))
2047 ast_indicate(in, AST_CONTROL_PROGRESS);
2049 case AST_CONTROL_VIDUPDATE:
2050 @@ -651,7 +655,7 @@ static struct ast_channel *wait_for_answ
2051 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name);
2052 if (single && CAN_EARLY_BRIDGE(peerflags))
2053 ast_rtp_early_bridge(in, c);
2054 - if (!ast_test_flag(outgoing, OPT_RINGBACK))
2055 + if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_NOINBAND))
2056 ast_indicate(in, AST_CONTROL_PROCEEDING);
2058 case AST_CONTROL_HOLD:
2059 @@ -669,7 +673,7 @@ static struct ast_channel *wait_for_answ
2060 /* Ignore going off hook and flash */
2063 - if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
2064 + if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK | OPT_NOINBAND)) {
2065 if (option_verbose > 2)
2066 ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name);
2067 ast_indicate(in, -1);
2068 @@ -1091,7 +1095,7 @@ static int dial_exec_full(struct ast_cha
2069 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
2072 - ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
2073 + ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_NOINBAND);
2074 /* loop through the list of dial destinations */
2076 while ((cur = strsep(&rest, "&")) ) {
2077 @@ -1116,7 +1120,7 @@ static int dial_exec_full(struct ast_cha
2078 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
2079 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
2080 OPT_CALLEE_PARK | OPT_CALLER_PARK |
2081 - OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
2082 + OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID | OPT_NOINBAND);
2083 ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);
2085 ast_copy_string(numsubst, number, sizeof(numsubst));
2086 @@ -1319,7 +1323,7 @@ static int dial_exec_full(struct ast_cha
2087 ast_moh_start(chan, NULL, NULL);
2089 ast_indicate(chan, AST_CONTROL_PROGRESS);
2090 - } else if (ast_test_flag(outgoing, OPT_RINGBACK)) {
2091 + } else if (ast_test_flag(outgoing, OPT_RINGBACK | OPT_NOINBAND)) {
2092 ast_indicate(chan, AST_CONTROL_RINGING);
2095 @@ -1442,7 +1446,7 @@ static int dial_exec_full(struct ast_cha
2097 if (ast_test_flag(&opts, OPT_MUSICBACK)) {
2099 - } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
2100 + } else if (ast_test_flag(&opts, OPT_RINGBACK | OPT_NOINBAND)) {
2101 ast_indicate(chan, -1);
2104 --- a/apps/app_dial.c
2105 +++ b/apps/app_dial.c
2106 @@ -201,7 +201,8 @@ static char *descrip =
2107 " R - indicate ringing to the calling party when the called party indicates\n"
2108 " ringing, pass no audio until answered.\n"
2109 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
2110 -" answered the call.\n"
2111 +" answered the call.\n"
2112 +" c - callback initiation, ring once and hangup.\n"
2113 " t - Allow the called party to transfer the calling party by sending the\n"
2114 " DTMF sequence defined in features.conf.\n"
2115 " T - Allow the calling party to transfer the called party by sending the\n"
2116 @@ -257,6 +258,7 @@ enum {
2117 OPT_CALLER_PARK = (1 << 26),
2118 OPT_IGNORE_FORWARDING = (1 << 27),
2119 OPT_NOINBAND = (1 << 28),
2120 + OPT_CALLBACK_INIT = (1 << 29),
2121 } dial_exec_option_flags;
2123 #define DIAL_STILLGOING (1 << 30)
2124 @@ -301,6 +303,7 @@ AST_APP_OPTIONS(dial_exec_options, {
2125 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
2126 AST_APP_OPTION('r', OPT_RINGBACK),
2127 AST_APP_OPTION('R', OPT_NOINBAND),
2128 + AST_APP_OPTION('c', OPT_CALLBACK_INIT),
2129 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
2130 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
2131 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
2132 @@ -621,14 +624,20 @@ static struct ast_channel *wait_for_answ
2133 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
2135 case AST_CONTROL_RINGING:
2136 - if (option_verbose > 2)
2137 + if (ast_test_flag(peerflags, OPT_CALLBACK_INIT)) {
2138 + if (option_verbose > 2)
2139 + ast_verbose( VERBOSE_PREFIX_3 "%s is ringing, hanging up.\n", o->chan->name);
2142 + if (option_verbose > 2)
2143 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name);
2144 - /* Setup early media if appropriate */
2145 - if (single && CAN_EARLY_BRIDGE(peerflags))
2146 + /* Setup early media if appropriate */
2147 + if (single && CAN_EARLY_BRIDGE(peerflags))
2148 ast_rtp_early_bridge(in, c);
2149 - if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
2150 + if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
2151 ast_indicate(in, AST_CONTROL_RINGING);
2156 case AST_CONTROL_PROGRESS:
2157 @@ -1095,7 +1104,7 @@ static int dial_exec_full(struct ast_cha
2158 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
2161 - ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_NOINBAND);
2162 + ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_CALLBACK_INIT | OPT_NOINBAND);
2163 /* loop through the list of dial destinations */
2165 while ((cur = strsep(&rest, "&")) ) {
2166 # Allow as many spans as Zaptel can take (defualt: 128).
2167 # There is a static array of zt_pris allocated at this size.
2168 # For that reason upstream only sort-of merged it: made it a
2169 # compile-time option in 1.6 .
2171 --- a/channels/chan_zap.c
2172 +++ b/channels/chan_zap.c
2173 @@ -190,7 +190,7 @@ static const char config[] = "zapata.con
2174 #define SIG_GR303FXOKS (0x0100000 | ZT_SIG_FXOKS)
2175 #define SIG_GR303FXSKS (0x0100000 | ZT_SIG_FXSKS)
2177 -#define NUM_SPANS 32
2178 +#define NUM_SPANS ZT_MAX_SPANS
2179 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
2180 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
2182 --- a/include/asterisk/channel.h
2183 +++ b/include/asterisk/channel.h
2184 @@ -435,6 +435,7 @@ struct ast_channel {
2185 unsigned int flags; /*!< channel flags of AST_FLAG_ type */
2186 unsigned short transfercapability; /*!< ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
2187 AST_LIST_HEAD_NOLOCK(, ast_frame) readq;
2188 + char lowlayercompat[16]; /*!< ISDN Low Layer Compatibility */
2191 int nativeformats; /*!< Kinds of data this channel can natively handle */
2192 --- a/channels/chan_zap.c
2193 +++ b/channels/chan_zap.c
2195 * the project provides a web site, mailing lists and IRC
2196 * channels for your use.
2198 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
2199 + * Klaus-Peter Junghanns <kpj@junghanns.net>
2202 * This program is free software, distributed under the terms of
2203 * the GNU General Public License Version 2. See the LICENSE file
2204 * at the top of the source tree.
2205 @@ -216,8 +220,6 @@ static struct ast_channel inuse;
2206 #ifdef PRI_GETSET_TIMERS
2207 static int pritimers[PRI_MAX_TIMERS];
2209 -static int pridebugfd = -1;
2210 -static char pridebugfilename[1024] = "";
2213 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
2214 @@ -235,10 +237,6 @@ AST_MUTEX_DEFINE_STATIC(iflock);
2216 static int ifcount = 0;
2219 -AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
2222 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
2223 when it's doing something critical. */
2224 AST_MUTEX_DEFINE_STATIC(monlock);
2225 @@ -253,6 +251,7 @@ static enum ast_bridge_result zt_bridge(
2227 static int zt_sendtext(struct ast_channel *c, const char *text);
2230 /*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
2231 static inline int zt_get_event(int fd)
2233 @@ -297,6 +296,14 @@ static int ringt_base = DEFAULT_RINGT;
2234 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
2235 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
2237 +struct zt_suspended_call {
2238 + ast_mutex_t lock; /* Mutex */
2239 + char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
2240 + char callid[10]; /* the callID provided by the user */
2241 + int parked_at; /* extension in the call parking context */
2242 + struct zt_suspended_call *next;
2246 pthread_t master; /*!< Thread of master */
2247 ast_mutex_t lock; /*!< Mutex */
2248 @@ -310,6 +317,8 @@ struct zt_pri {
2249 int nsf; /*!< Network-Specific Facilities */
2250 int dialplan; /*!< Dialing plan */
2251 int localdialplan; /*!< Local dialing plan */
2252 + char nocid[AST_MAX_EXTENSION]; /*!< CallerID string to use if none provided */
2253 + char withheldcid[AST_MAX_EXTENSION]; /*!< CallerID string to use if CallerID is withheld */
2254 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
2255 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
2256 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
2257 @@ -321,6 +330,7 @@ struct zt_pri {
2258 int prilogicalspan; /*!< Logical span number within trunk group */
2259 int numchans; /*!< Num of channels we represent */
2260 int overlapdial; /*!< In overlap dialing mode */
2262 int facilityenable; /*!< Enable facility IEs */
2263 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
2264 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
2265 @@ -336,6 +346,8 @@ struct zt_pri {
2266 struct zt_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
2267 struct zt_pvt *crvs; /*!< Member CRV structs */
2268 struct zt_pvt *crvend; /*!< Pointer to end of CRV structs */
2269 + struct zt_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
2274 @@ -453,6 +465,8 @@ static struct zt_pvt {
2275 unsigned int echocanbridged:1;
2276 unsigned int echocanon:1;
2277 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
2278 + /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
2279 + on a zap channel with EC to be off no matter what happens. */
2280 unsigned int firstradio:1;
2281 unsigned int hanguponpolarityswitch:1;
2282 unsigned int hardwaredtmf:1;
2283 @@ -467,7 +481,8 @@ static struct zt_pvt {
2284 unsigned int overlapdial:1;
2285 unsigned int permcallwaiting:1;
2286 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
2287 - unsigned int priindication_oob:1;
2288 + unsigned int priindication_oob:2;
2289 + unsigned int pritransfer:2;
2290 unsigned int priexclusive:1;
2291 unsigned int pulse:1;
2292 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
2293 @@ -504,6 +519,7 @@ static struct zt_pvt {
2295 char cid_num[AST_MAX_EXTENSION];
2296 int cid_ton; /*!< Type Of Number (TON) */
2297 + int cid_pres; /*!< Calling Presentation */
2298 char cid_name[AST_MAX_EXTENSION];
2299 char lastcid_num[AST_MAX_EXTENSION];
2300 char lastcid_name[AST_MAX_EXTENSION];
2301 @@ -569,6 +585,8 @@ static struct zt_pvt {
2302 struct zt_pvt *bearer;
2303 struct zt_pvt *realcall;
2305 + int tei; /* channel in use by this tei */
2306 + q931_call *holdedcall;
2310 @@ -614,11 +632,14 @@ static struct zt_chan_conf zt_chan_conf_
2314 + .nocid = "No CID available",
2315 + .withheldcid = "CID withheld",
2316 .internationalprefix = "",
2317 .nationalprefix = "",
2319 .privateprefix = "",
2320 .unknownprefix = "",
2323 .resetinterval = 3600
2325 @@ -630,6 +651,8 @@ static struct zt_chan_conf zt_chan_conf_
2326 .mohinterpret = "default",
2328 .transfertobusy = 1,
2329 + .priindication_oob = 0,
2332 .cid_signalling = CID_SIG_BELL,
2333 .cid_start = CID_START_RING,
2334 @@ -684,6 +707,8 @@ static int zt_indicate(struct ast_channe
2335 static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
2336 static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
2337 static int zt_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
2338 +static void enable_dtmf_detect(struct zt_pvt *p);
2339 +static void disable_dtmf_detect(struct zt_pvt *p);
2341 static const struct ast_channel_tech zap_tech = {
2343 @@ -715,6 +740,13 @@ static const struct ast_channel_tech zap
2344 struct zt_pvt *round_robin[32];
2350 + struct ast_channel *chan;
2354 static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
2357 @@ -1417,12 +1449,16 @@ static void zt_enable_ec(struct zt_pvt *
2361 + if (p->faxhandled) {
2362 + ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
2366 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
2370 - ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
2371 + ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
2374 if (p->echocancel) {
2375 @@ -1449,7 +1485,7 @@ static void zt_train_ec(struct zt_pvt *p
2379 - if (p && p->echocancel && p->echotraining) {
2380 + if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
2381 x = p->echotraining;
2382 res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
2384 @@ -1810,7 +1846,12 @@ static int zt_call(struct ast_channel *a
2385 ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
2388 - set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
2389 + if (IS_DIGITAL(ast->transfercapability)) {
2390 + set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
2392 + set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
2397 if (p->outsigmod > -1)
2398 @@ -2041,6 +2082,7 @@ static int zt_call(struct ast_channel *a
2400 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2401 p->dialdest[0] = '\0';
2402 + disable_dtmf_detect(p);
2405 ast_log(LOG_DEBUG, "not yet implemented\n");
2406 @@ -2061,6 +2103,12 @@ static int zt_call(struct ast_channel *a
2408 int redirect_reason;
2410 + if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
2411 + // pass NO audio when ringing an isdn phone
2413 + // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
2416 c = strchr(dest, '/');
2419 @@ -2083,6 +2131,7 @@ static int zt_call(struct ast_channel *a
2420 ast_mutex_unlock(&p->lock);
2423 + strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
2424 if (mysig != SIG_FXSKS) {
2425 p->dop.op = ZT_DIAL_OP_REPLACE;
2426 s = strchr(c + p->stripmsd, 'w');
2427 @@ -2106,6 +2155,8 @@ static int zt_call(struct ast_channel *a
2429 ast_mutex_unlock(&p->lock);
2432 + // ast_log(LOG_NOTICE, "call %d\n", p->call);
2434 if (!(sr = pri_sr_new())) {
2435 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2436 @@ -2135,7 +2186,7 @@ static int zt_call(struct ast_channel *a
2437 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2438 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2440 - ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2441 + ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
2442 if (p->pri->facilityenable)
2443 pri_facility_enable(p->pri->pri);
2445 @@ -2399,8 +2450,10 @@ static int pri_find_dchan(struct zt_pri
2449 - ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2450 + if (pri->nodetype != BRI_CPE_PTMP) {
2451 + ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2452 pri->dchannels[newslot]);
2455 if (old && (oldslot != newslot))
2456 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2457 @@ -2410,6 +2463,16 @@ static int pri_find_dchan(struct zt_pri
2461 +static int zt_setlaw(int zfd, int law)
2464 + res = ioctl(zfd, ZT_SETLAW, &law);
2471 static int zt_hangup(struct ast_channel *ast)
2474 @@ -2457,8 +2520,7 @@ static int zt_hangup(struct ast_channel
2476 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2477 p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
2478 - p->ignoredtmf = 0;
2482 /* Real channel, do some fixup */
2483 p->subs[index].owner = NULL;
2484 @@ -2560,6 +2622,7 @@ static int zt_hangup(struct ast_channel
2487 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2488 + int outgoing = p->outgoing;
2491 p->distinctivering = 0;
2492 @@ -2602,7 +2665,7 @@ static int zt_hangup(struct ast_channel
2493 pri_call_set_useruser(p->call, useruser);
2496 - pri_hangup(p->pri->pri, p->call, -1);
2497 + pri_hangup(p->pri->pri, p->call, -1, -1);
2500 p->bearer->call = NULL;
2501 @@ -2622,7 +2685,28 @@ static int zt_hangup(struct ast_channel
2503 icause = atoi(cause);
2505 - pri_hangup(p->pri->pri, p->call, icause);
2507 + pri_hangup(p->pri->pri, p->call, icause, -1);
2509 + /* if we send a rel9999ease complete we wont ge no hangup event, so clear the call here */
2510 + if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
2511 + if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING) || (ast->_state == AST_STATE_RESERVED)) {
2514 + ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
2515 + icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
2519 + if (p->pri->nodetype == BRI_NETWORK_PTMP) {
2520 + if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
2530 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2531 @@ -2806,10 +2890,14 @@ static int zt_answer(struct ast_channel
2533 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
2535 + /* stop ignoring inband dtmf */
2536 + enable_dtmf_detect(p);
2538 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2541 + /* the audio path is complete now, train the echo canceler */
2546 @@ -3446,6 +3534,15 @@ static int zt_fixup(struct ast_channel *
2548 struct zt_pvt *p = newchan->tech_pvt;
2550 + if (newchan && newchan->tech_pvt) {
2551 + p = newchan->tech_pvt;
2555 + ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
2559 ast_mutex_lock(&p->lock);
2560 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
2561 if (p->owner == oldchan) {
2562 @@ -3655,8 +3752,10 @@ static void zt_handle_dtmfup(struct ast_
2563 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
2564 if (ast_async_goto(ast, target_context, "fax", 1))
2565 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
2568 + if (option_verbose > 2)
2569 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
2571 } else if (option_debug)
2572 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2573 } else if (option_debug)
2574 @@ -3815,7 +3914,7 @@ static struct ast_frame *zt_handle_event
2576 if (p->pri && p->pri->pri) {
2577 if (!pri_grab(p, p->pri)) {
2578 - pri_hangup(p->pri->pri, p->call, -1);
2579 + pri_hangup(p->pri->pri, p->call, -1, -1);
2580 pri_destroycall(p->pri->pri, p->call);
2583 @@ -4886,7 +4985,7 @@ static struct ast_frame *zt_read(struct
2584 p->subs[index].f.data = NULL;
2585 p->subs[index].f.datalen= 0;
2587 - if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
2588 + if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
2589 /* Perform busy detection. etc on the zap line */
2590 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
2592 @@ -4898,8 +4997,9 @@ static struct ast_frame *zt_read(struct
2594 } else if (f->frametype == AST_FRAME_DTMF) {
2596 - if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
2597 - /* Don't accept in-band DTMF when in overlap dial mode */
2598 + if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
2599 + /* Don't accept in-band DTMF when in overlap dial mode
2600 + or when in non-overlap overlapdialing mode ... */
2601 f->frametype = AST_FRAME_NULL;
2604 @@ -4974,7 +5074,9 @@ static int zt_write(struct ast_channel *
2606 /* Write a frame of (presumably voice) data */
2607 if (frame->frametype != AST_FRAME_VOICE) {
2608 - if (frame->frametype != AST_FRAME_IMAGE)
2609 + if (frame->frametype == AST_FRAME_TEXT) {
2610 + ast_log(LOG_NOTICE, "text\n");
2611 + } else if (frame->frametype != AST_FRAME_IMAGE)
2612 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
2615 @@ -5042,7 +5144,7 @@ static int zt_indicate(struct ast_channe
2616 switch (condition) {
2617 case AST_CONTROL_BUSY:
2619 - if (p->priindication_oob && p->sig == SIG_PRI) {
2620 + if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
2621 chan->hangupcause = AST_CAUSE_USER_BUSY;
2622 chan->_softhangup |= AST_SOFTHANGUP_DEV;
2624 @@ -5124,7 +5226,7 @@ static int zt_indicate(struct ast_channe
2625 case AST_CONTROL_CONGESTION:
2626 chan->hangupcause = AST_CAUSE_CONGESTION;
2628 - if (p->priindication_oob && p->sig == SIG_PRI) {
2629 + if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
2630 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
2631 chan->_softhangup |= AST_SOFTHANGUP_DEV;
2633 @@ -5321,8 +5423,12 @@ static struct ast_channel *zt_new(struct
2634 if (state == AST_STATE_RING)
2638 + if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
2640 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
2641 - /* Only FXO signalled stuff can be picked up */
2643 + /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
2644 tmp->callgroup = i->callgroup;
2645 tmp->pickupgroup = i->pickupgroup;
2647 @@ -5452,6 +5558,7 @@ static void *ss_thread(void *data)
2653 /* in the bizarre case where the channel has become a zombie before we
2654 even get started here, abort safely
2655 @@ -5480,10 +5587,17 @@ static void *ss_thread(void *data)
2656 len = strlen(exten);
2658 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
2659 - if (len && !ast_ignore_pattern(chan->context, exten))
2660 + if (len && !ast_ignore_pattern(chan->context, exten)) {
2661 tone_zone_play_tone(p->subs[index].zfd, -1);
2663 - tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
2665 + network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
2667 + tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
2669 + /* cpe be quiet */
2670 + tone_zone_play_tone(p->subs[index].zfd, -1);
2673 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
2674 timeout = matchdigittimeout;
2676 @@ -6697,9 +6811,20 @@ static int handle_init_event(struct zt_p
2677 case ZT_EVENT_NOALARM:
2679 if (!i->unknown_alarm) {
2682 + if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
2683 + /* dont annoy BRI TE mode users with layer2layer alarms */
2686 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
2687 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
2688 "Channel: %d\r\n", i->channel);
2695 i->unknown_alarm = 0;
2697 @@ -6708,7 +6833,13 @@ static int handle_init_event(struct zt_p
2699 res = get_alarms(i);
2701 - const char *alarm_str = alarm2str(res);
2704 + if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
2705 + /* dont annoy BRI TE mode users with layer2layer alarms */
2708 + const char *alarm_str = alarm2str(res);
2710 /* hack alert! Zaptel 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
2711 * doesn't know what to do with it. Don't confuse users with log messages. */
2712 @@ -6724,6 +6855,10 @@ static int handle_init_event(struct zt_p
2715 alarm_str, i->channel);
2721 /* fall thru intentionally */
2722 case ZT_EVENT_ONHOOK:
2723 @@ -6768,8 +6903,10 @@ static int handle_init_event(struct zt_p
2724 zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
2728 - res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
2729 + if (event != ZT_EVENT_ALARM) {
2731 + res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
2735 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
2736 @@ -7062,6 +7199,8 @@ static int pri_resolve_span(int *span, i
2738 if (si->totalchans == 31) { /* if it's an E1 */
2739 pris[*span].dchannels[0] = 16 + offset;
2740 + } else if (si->totalchans == 3) { /* if it's an S0 ZAPBRI */
2741 + pris[*span].dchannels[0] = 3 + offset;
2743 pris[*span].dchannels[0] = 24 + offset;
2745 @@ -7314,6 +7453,11 @@ static struct zt_pvt *mkintf(int channel
2746 destroy_zt_pvt(&tmp);
2749 + if ((pris[span].localdialplan) && (pris[span].localdialplan != conf->pri.localdialplan)) {
2750 + ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
2751 + destroy_zt_pvt(&tmp);
2754 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
2755 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
2756 destroy_zt_pvt(&tmp);
2757 @@ -7331,6 +7475,11 @@ static struct zt_pvt *mkintf(int channel
2760 pris[span].nodetype = conf->pri.nodetype;
2762 + if (conf->pri.nodetype == BRI_NETWORK_PTMP) {
2763 + pris[span].dchanavail[0] = DCHAN_AVAILABLE;
2764 + pri_find_dchan(&pris[span]);
2766 pris[span].switchtype = myswitchtype;
2767 pris[span].nsf = conf->pri.nsf;
2768 pris[span].dialplan = conf->pri.dialplan;
2769 @@ -7339,9 +7488,13 @@ static struct zt_pvt *mkintf(int channel
2770 pris[span].minunused = conf->pri.minunused;
2771 pris[span].minidle = conf->pri.minidle;
2772 pris[span].overlapdial = conf->pri.overlapdial;
2773 + pris[span].usercid = conf->pri.usercid;
2774 + pris[span].suspended_calls = NULL;
2775 pris[span].facilityenable = conf->pri.facilityenable;
2776 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
2777 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
2778 + ast_copy_string(pris[span].nocid, conf->pri.nocid, sizeof(pris[span].nocid));
2779 + ast_copy_string(pris[span].withheldcid, conf->pri.withheldcid, sizeof(pris[span].withheldcid));
2780 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
2781 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
2782 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
2783 @@ -7483,6 +7636,7 @@ static struct zt_pvt *mkintf(int channel
2784 tmp->restrictcid = conf->chan.restrictcid;
2785 tmp->use_callingpres = conf->chan.use_callingpres;
2786 tmp->priindication_oob = conf->chan.priindication_oob;
2787 + tmp->pritransfer = conf->chan.pritransfer;
2788 tmp->priexclusive = conf->chan.priexclusive;
2789 if (tmp->usedistinctiveringdetection) {
2790 if (!tmp->use_callerid) {
2791 @@ -7765,7 +7919,7 @@ static int pri_find_empty_chan(struct zt
2793 if (!backwards && (x >= pri->numchans))
2795 - if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
2796 + if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
2797 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
2798 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
2800 @@ -7961,6 +8115,11 @@ static struct ast_channel *zt_request(co
2803 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
2804 + } else if (opt == 'm') {
2805 + /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
2806 + p->faxhandled = 1;
2808 + tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
2810 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
2812 @@ -7994,13 +8153,14 @@ next:
2813 *cause = AST_CAUSE_BUSY;
2814 } else if (groupmatched) {
2815 *cause = AST_CAUSE_CONGESTION;
2817 + *cause = AST_CAUSE_CONGESTION;
2826 static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
2828 @@ -8045,6 +8205,7 @@ static int pri_find_principle(struct zt_
2829 static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
2836 @@ -8075,6 +8236,7 @@ static int pri_fixup_principle(struct zt
2838 /* Fix it all up now */
2839 new->owner = old->owner;
2840 + new->outgoing = old->outgoing;
2843 ast_string_field_build(new->owner, name,
2844 @@ -8094,6 +8256,34 @@ static int pri_fixup_principle(struct zt
2845 new->dsp_features = old->dsp_features;
2847 old->dsp_features = 0;
2849 + /* Copy faxhandled/digial, alreadyhungup */
2850 + new->faxhandled = old->faxhandled;
2851 + new->digital = old->digital;
2852 + new->alreadyhungup = old->alreadyhungup;
2854 + /* Copy law, gains, etc */
2855 + new->law = old->law;
2856 + if (ioctl(new->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &new->law) == -1)
2857 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", new->channel, new->law);
2858 + res = zt_setlaw(new->subs[SUB_REAL].zfd, new->law);
2860 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", new->channel);
2861 + if (!new->digital) {
2862 + res = set_actual_gain(new->subs[SUB_REAL].zfd, 0, new->rxgain, new->txgain, new->law);
2864 + res = set_actual_gain(new->subs[SUB_REAL].zfd, 0, 0, 0, new->law);
2867 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", new->channel);
2869 + /* Shutdown old channel */
2870 + zt_confmute(old, 0);
2873 + restore_gains(old);
2874 + zt_disable_ec(old);
2875 + zt_setlinear(old->subs[SUB_REAL].zfd, 0);
2879 @@ -8122,7 +8312,9 @@ static int pri_fixup_principle(struct zt
2883 - ast_log(LOG_WARNING, "Call specified, but not found?\n");
2884 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
2885 + ast_log(LOG_WARNING, "Call specified, but not found?\n");
2890 @@ -8181,86 +8373,21 @@ static void *do_idle_thread(void *vchan)
2892 #error "Upgrade your libpri"
2894 -static void zt_pri_message(struct pri *pri, char *s)
2895 +static void zt_pri_message(char *s, int span)
2898 - int dchan = -1, span = -1;
2899 - int dchancount = 0;
2902 - for (x = 0; x < NUM_SPANS; x++) {
2903 - for (y = 0; y < NUM_DCHANS; y++) {
2904 - if (pris[x].dchans[y])
2907 - if (pris[x].dchans[y] == pri)
2916 - if ((dchan >= 0) && (span >= 0)) {
2917 - if (dchancount > 1)
2918 - ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
2920 - ast_verbose("%s", s);
2922 - ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
2924 - ast_verbose("%s", s);
2926 - ast_mutex_lock(&pridebugfdlock);
2928 - if (pridebugfd >= 0)
2929 - write(pridebugfd, s, strlen(s));
2931 - ast_mutex_unlock(&pridebugfdlock);
2932 + ast_verbose("%d %s", span, s);
2935 -static void zt_pri_error(struct pri *pri, char *s)
2936 +static void zt_pri_error(char *s, int span)
2939 - int dchan = -1, span = -1;
2940 - int dchancount = 0;
2943 - for (x = 0; x < NUM_SPANS; x++) {
2944 - for (y = 0; y < NUM_DCHANS; y++) {
2945 - if (pris[x].dchans[y])
2948 - if (pris[x].dchans[y] == pri)
2957 - if ((dchan >= 0) && (span >= 0)) {
2958 - if (dchancount > 1)
2959 - ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
2961 - ast_log(LOG_ERROR, "%s", s);
2963 - ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
2965 - ast_log(LOG_ERROR, "%s", s);
2967 - ast_mutex_lock(&pridebugfdlock);
2969 - if (pridebugfd >= 0)
2970 - write(pridebugfd, s, strlen(s));
2972 - ast_mutex_unlock(&pridebugfdlock);
2973 + ast_log(LOG_WARNING, "%d %s", span, s);
2976 static int pri_check_restart(struct zt_pri *pri)
2978 + if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
2983 } while ((pri->resetpos < pri->numchans) &&
2984 @@ -8344,13 +8471,30 @@ static void apply_plan_to_number(char *b
2988 -static int zt_setlaw(int zfd, int law)
2991 - res = ioctl(zfd, ZT_SETLAW, &law);
2995 +static void pri_make_callerid(struct zt_pri *pri, char *callerid, int callerid_len, char *callingnum, int callingnum_len, int callingplan, int callingpres, int stripmsd) {
2996 + if (callingnum && (callingnum_len > stripmsd)) {
2997 + callingnum += stripmsd;
2999 + switch (callingplan) {
3000 + case PRI_INTERNATIONAL_ISDN:
3001 + snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
3003 + case PRI_NATIONAL_ISDN:
3004 + snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
3006 + case PRI_LOCAL_ISDN:
3007 + snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
3010 + snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
3013 + snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
3016 + snprintf(callerid, callerid_len, "%s", callingnum);
3021 static void *pri_dchannel(void *vpri)
3022 @@ -8530,15 +8674,44 @@ static void *pri_dchannel(void *vpri)
3023 /* Check for an event */
3025 res = ioctl(pri->fds[which], ZT_GETEVENT, &x);
3027 + if ((pri->nodetype != BRI_CPE) && (pri->nodetype != BRI_CPE_PTMP)) {
3028 + /* dont annoy BRI TE mode users with layer2layer alarms */
3030 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
3032 /* Keep track of alarm state */
3033 if (x == ZT_EVENT_ALARM) {
3034 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
3035 pri_find_dchan(pri);
3036 + if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
3038 + for (i=0; i<pri->numchans; i++) {
3039 + struct zt_pvt *p = pri->pvts[i];
3042 + if (p->pri && p->pri->pri) {
3043 + pri_destroycall(p->pri->pri, p->call);
3047 + ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
3050 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3054 + pri_shutdown(pri->pri);
3057 } else if (x == ZT_EVENT_NOALARM) {
3058 - pri->dchanavail[which] |= DCHAN_NOTINALARM;
3059 - pri_restart(pri->dchans[which]);
3060 + if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
3061 + pri->dchanavail[which] |= DCHAN_NOTINALARM;
3062 + // pri->dchanavail[which] |= DCHAN_UP;
3064 + pri->dchanavail[which] |= DCHAN_NOTINALARM;
3065 + pri_restart(pri->dchans[which]);
3070 @@ -8550,8 +8723,7 @@ static void *pri_dchannel(void *vpri)
3073 } else if (errno != EINTR)
3074 - ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
3076 + ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
3079 pri_dump_event(pri->dchans[which], e);
3080 @@ -8576,6 +8748,17 @@ static void *pri_dchannel(void *vpri)
3083 case PRI_EVENT_DCHAN_UP:
3084 + if (pri->nodetype == BRI_NETWORK_PTMP) {
3085 + if (option_verbose > 3)
3086 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
3087 + } else if (pri->nodetype == BRI_CPE_PTMP) {
3088 + if (option_verbose > 3)
3089 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
3091 + if (option_verbose > 1)
3092 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
3095 if (!pri->pri) pri_find_dchan(pri);
3097 /* Note presense of D-channel */
3098 @@ -8594,6 +8777,12 @@ static void *pri_dchannel(void *vpri)
3101 case PRI_EVENT_DCHAN_DOWN:
3102 + if (pri->nodetype == BRI_NETWORK_PTMP) {
3103 + if (option_verbose > 3)
3104 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
3105 + // PTMP BRIs have N dchans, handled by libpri
3106 + if (e->gen.tei == 0) break;
3108 pri_find_dchan(pri);
3109 if (!pri_is_up(pri)) {
3111 @@ -8601,16 +8790,18 @@ static void *pri_dchannel(void *vpri)
3112 for (i = 0; i < pri->numchans; i++) {
3113 struct zt_pvt *p = pri->pvts[i];
3115 + if ((p->tei == e->gen.tei) || (pri->nodetype != BRI_NETWORK_PTMP)) {
3116 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
3117 /* T309 is not enabled : hangup calls when alarm occurs */
3119 if (p->pri && p->pri->pri) {
3120 - pri_hangup(p->pri->pri, p->call, -1);
3121 + pri_hangup(p->pri->pri, p->call, -1, -1);
3122 pri_destroycall(p->pri->pri, p->call);
3125 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
3129 pri_hangup_all(p->realcall, pri);
3130 } else if (p->owner)
3131 @@ -8619,6 +8810,7 @@ static void *pri_dchannel(void *vpri)
3138 case PRI_EVENT_RESTART:
3139 @@ -8653,8 +8845,8 @@ static void *pri_dchannel(void *vpri)
3140 pri_destroycall(pri->pri, pri->pvts[x]->call);
3141 pri->pvts[x]->call = NULL;
3143 - if (pri->pvts[chanpos]->realcall)
3144 - pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
3145 + if (pri->pvts[x]->realcall)
3146 + pri_hangup_all(pri->pvts[x]->realcall, pri);
3147 else if (pri->pvts[x]->owner)
3148 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3149 ast_mutex_unlock(&pri->pvts[x]->lock);
3150 @@ -8688,7 +8880,6 @@ static void *pri_dchannel(void *vpri)
3155 case PRI_EVENT_INFO_RECEIVED:
3156 chanpos = pri_find_principle(pri, e->ring.channel);
3158 @@ -8697,9 +8888,11 @@ static void *pri_dchannel(void *vpri)
3160 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
3162 +// ast_log(LOG_NOTICE, "INFO received on channel %d/%d span %d\n",
3163 +// PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3164 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3165 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
3166 - if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
3167 + if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
3168 /* how to do that */
3169 int digitlen = strlen(e->ring.callednum);
3171 @@ -8711,6 +8904,14 @@ static void *pri_dchannel(void *vpri)
3172 zap_queue_frame(pri->pvts[chanpos], &f, pri);
3175 + if (!pri->overlapdial) {
3176 + strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
3177 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
3178 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
3180 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
3184 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3186 @@ -8718,36 +8919,59 @@ static void *pri_dchannel(void *vpri)
3188 case PRI_EVENT_RING:
3190 - if (e->ring.channel == -1)
3191 + if (e->ring.channel == -1) {
3192 + /* if no channel specified find one empty */
3193 chanpos = pri_find_empty_chan(pri, 1);
3196 chanpos = pri_find_principle(pri, e->ring.channel);
3198 /* if no channel specified find one empty */
3200 - ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
3201 - PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3202 + /* no channel specified and no free channel. this is a callwating SETUP */
3203 + if (e->ring.channel <= 0) {
3204 + if (option_verbose > 2)
3205 + ast_verbose(VERBOSE_PREFIX_3 "Ignoring callwaiting SETUP on channel %d/%d span %d %d\n", PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span, e->ring.channel);
3206 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY, -1);
3210 + /* ok, we got a b channel for this call, lock it */
3211 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3212 if (pri->pvts[chanpos]->owner) {
3213 - if (pri->pvts[chanpos]->call == e->ring.call) {
3214 - ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
3215 + /* safety check, for messed up retransmissions? */
3216 + if (pri->pvts[chanpos]->call == e->ring.call) {
3217 + ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
3218 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3220 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3224 + ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
3225 + PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3226 + if (pri->pvts[chanpos]->realcall) {
3227 + pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
3229 - /* This is where we handle initial glare */
3230 - ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
3231 - PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
3232 - ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3234 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3235 + /* XXX destroy the call here, so we can accept the retransmission as a new call */
3236 + pri_destroycall(pri->pri, e->ring.call);
3240 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3245 + if (chanpos > -1) {
3246 + /* everything is ok with the b channel */
3247 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3250 - if ((chanpos < 0) && (e->ring.flexible))
3251 - chanpos = pri_find_empty_chan(pri, 1);
3252 + /* actually, we already got a valid channel by now */
3254 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3255 + /* dont detect dtmfs before the signalling is done */
3256 + disable_dtmf_detect(pri->pvts[chanpos]);
3257 + /* this channel is owned by this TEI */
3258 + pri->pvts[chanpos]->tei = e->ring.tei;
3259 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
3260 /* Should be safe to lock CRV AFAIK while bearer is still locked */
3261 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
3262 @@ -8761,13 +8985,14 @@ static void *pri_dchannel(void *vpri)
3263 ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
3265 ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
3266 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
3267 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE, -1);
3269 ast_mutex_unlock(&crv->lock);
3270 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3274 + /* assign call to b channel */
3275 pri->pvts[chanpos]->call = e->ring.call;
3276 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
3277 if (pri->pvts[chanpos]->use_callerid) {
3278 @@ -8792,34 +9017,82 @@ static void *pri_dchannel(void *vpri)
3280 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
3281 e->ring.redirectingnum, e->ring.callingplanrdnis);
3282 + /* get callingpres */
3283 + pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
3284 + switch (e->ring.callingpres) {
3285 + case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
3286 + case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
3287 + case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
3288 + case PRES_PROHIB_NETWORK_NUMBER:
3289 + ast_copy_string(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
3291 + case PRES_NUMBER_NOT_AVAILABLE:
3292 + ast_copy_string(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
3295 /* If immediate=yes go to s|1 */
3296 if (pri->pvts[chanpos]->immediate) {
3297 if (option_verbose > 2)
3298 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
3299 pri->pvts[chanpos]->exten[0] = 's';
3300 pri->pvts[chanpos]->exten[1] = '\0';
3302 - /* Get called number */
3303 - else if (!ast_strlen_zero(e->ring.callednum)) {
3304 - ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
3305 - ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
3306 - } else if (pri->overlapdial)
3307 - pri->pvts[chanpos]->exten[0] = '\0';
3309 - /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
3310 - pri->pvts[chanpos]->exten[0] = 's';
3311 - pri->pvts[chanpos]->exten[1] = '\0';
3313 - /* Set DNID on all incoming calls -- even immediate */
3314 - if (!ast_strlen_zero(e->ring.callednum))
3315 - ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
3316 - /* No number yet, but received "sending complete"? */
3317 - if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
3318 + } else if (ast_strlen_zero(e->ring.callednum)) {
3319 + /* called party number is empty */
3320 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
3321 + if (!pri->overlapdial) {
3322 + // be able to set digittimeout for BRI phones
3323 + pri->pvts[chanpos]->exten[0] = 's';
3324 + pri->pvts[chanpos]->exten[1] = '\0';
3325 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
3327 + pri->pvts[chanpos]->exten[0] = '\0';
3330 + if (pri->nodetype == BRI_CPE) {
3331 + /* fix for .at p2p bri lines */
3332 + pri->pvts[chanpos]->exten[0] = 's';
3333 + pri->pvts[chanpos]->exten[1] = '\0';
3334 + } else if (pri->overlapdial) {
3335 + pri->pvts[chanpos]->exten[0] = '\0';
3337 + /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
3338 + pri->pvts[chanpos]->exten[0] = 's';
3339 + pri->pvts[chanpos]->exten[1] = '\0';
3342 + /* No number yet, but received "sending complete"? */
3343 + if (e->ring.complete) {
3344 if (option_verbose > 2)
3345 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
3346 pri->pvts[chanpos]->exten[0] = 's';
3347 pri->pvts[chanpos]->exten[1] = '\0';
3351 + /* Get called number */
3352 + pri_make_callerid(pri, pri->pvts[chanpos]->dnid, sizeof(pri->pvts[chanpos]->dnid), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
3353 + pri_make_callerid(pri, pri->pvts[chanpos]->exten, sizeof(pri->pvts[chanpos]->exten), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
3354 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
3355 + /* if we get the next digit we should stop the dialtone */
3356 + if (!pri->overlapdial) {
3357 + // with overlapdial=no the exten is always prefixed by "s"
3358 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
3359 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
3361 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
3364 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
3365 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
3367 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
3372 + /* Part 3: create channel, setup audio... */
3373 + /* Set DNID on all incoming calls -- even immediate */
3374 + if (!ast_strlen_zero(e->ring.callednum))
3375 + strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
3376 /* Make sure extension exists (or in overlap dial mode, can exist) */
3377 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
3378 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
3379 @@ -8838,19 +9111,36 @@ static void *pri_dchannel(void *vpri)
3380 res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
3382 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
3383 - res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
3384 + if (IS_DIGITAL(e->ring.ctype)) {
3385 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
3387 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
3390 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
3391 - if (e->ring.complete || !pri->overlapdial) {
3392 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3393 + if (e->ring.complete || !pri->overlapdial) {
3394 /* Just announce proceeding */
3395 pri->pvts[chanpos]->proceeding = 1;
3396 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
3399 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
3400 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
3402 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
3405 + /* BRI_NETWORK | BRI_NETWORK_PTMP */
3406 + if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
3407 + /* send a SETUP_ACKNOWLEDGE */
3408 + pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
3410 + /* send an ALERTING ??? wtf */
3411 + // pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
3412 + pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
3415 + /* overlapdial = yes and the extension can be valid */
3416 /* Get the use_callingpres state */
3417 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
3419 @@ -8862,10 +9152,17 @@ static void *pri_dchannel(void *vpri)
3420 /* Set bearer and such */
3421 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
3422 c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
3423 + if (c && (e->ring.lowlayercompat[0] > 0)) {
3424 + memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
3426 pri->pvts[chanpos]->owner = &inuse;
3427 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
3429 c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
3430 + if (c && (e->ring.lowlayercompat[0] > 0)) {
3431 + memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
3433 + zt_enable_ec(pri->pvts[chanpos]); /* XXX rethink */
3436 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3437 @@ -8873,6 +9170,16 @@ static void *pri_dchannel(void *vpri)
3438 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
3439 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
3441 + if (!ast_strlen_zero(e->ring.callingnum)) {
3443 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
3444 + pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
3446 + if (!ast_strlen_zero(e->ring.callingani)) {
3448 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
3449 + pbx_builtin_setvar_helper(c, "PRI_USER_CID", tmpstr);
3451 if (e->ring.ani2 >= 0) {
3452 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
3453 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
3454 @@ -8896,8 +9203,8 @@ static void *pri_dchannel(void *vpri)
3455 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3456 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
3457 if (option_verbose > 2)
3458 - ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
3459 - plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
3460 + ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
3461 + pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
3462 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
3464 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
3465 @@ -8905,15 +9212,19 @@ static void *pri_dchannel(void *vpri)
3469 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
3470 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
3471 pri->pvts[chanpos]->call = NULL;
3474 pthread_attr_destroy(&attr);
3476 + /* overlapdial = no */
3477 ast_mutex_unlock(&pri->lock);
3478 /* Release PRI lock while we create the channel */
3479 c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
3480 + if (c && (e->ring.lowlayercompat[0] > 0)) {
3481 + memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
3484 char calledtonstr[10];
3486 @@ -8940,26 +9251,43 @@ static void *pri_dchannel(void *vpri)
3487 ast_mutex_lock(&pri->lock);
3489 if (option_verbose > 2)
3490 - ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
3491 - plancallingnum, pri->pvts[chanpos]->exten,
3492 + ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
3493 + pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten,
3494 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
3495 zt_enable_ec(pri->pvts[chanpos]);
3496 + if(!ast_strlen_zero(e->ring.callingsubaddr)) {
3497 + pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
3499 + if (!ast_strlen_zero(e->ring.callingnum)) {
3501 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
3502 + pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
3504 + if (!ast_strlen_zero(e->ring.callingani)) {
3506 + pri_make_callerid(pri, tmpstr,sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
3507 + pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
3509 + if (!ast_strlen_zero(e->ring.useruserinfo)) {
3510 + pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
3514 ast_mutex_lock(&pri->lock);
3516 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
3517 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
3518 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
3519 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
3520 pri->pvts[chanpos]->call = NULL;
3524 + /* invalid extension */
3525 if (option_verbose > 2)
3526 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
3527 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
3528 pri->pvts[chanpos]->prioffset, pri->span);
3529 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
3530 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED, -1);
3531 pri->pvts[chanpos]->call = NULL;
3532 pri->pvts[chanpos]->exten[0] = '\0';
3534 @@ -8968,9 +9296,9 @@ static void *pri_dchannel(void *vpri)
3535 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3537 if (e->ring.flexible)
3538 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
3539 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION, -1);
3541 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
3542 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, -1);
3545 case PRI_EVENT_RINGING:
3546 @@ -8986,7 +9314,7 @@ static void *pri_dchannel(void *vpri)
3548 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3549 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
3550 - zt_enable_ec(pri->pvts[chanpos]);
3551 + // XXX zt_enable_ec(pri->pvts[chanpos]);
3552 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
3553 pri->pvts[chanpos]->alerting = 1;
3555 @@ -9018,9 +9346,16 @@ static void *pri_dchannel(void *vpri)
3558 case PRI_EVENT_PROGRESS:
3559 - /* Get chan value if e->e is not PRI_EVNT_RINGING */
3560 + /* Get chan value if e->e is not PRI_EVENT_RINGING */
3561 chanpos = pri_find_principle(pri, e->proceeding.channel);
3563 + if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
3564 + /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
3565 + if (pri->pvts[chanpos]->owner) {
3566 + pri->pvts[chanpos]->owner->hangupcause = AST_CAUSE_USER_BUSY;
3567 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3570 #ifdef PRI_PROGRESS_MASK
3571 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
3573 @@ -9062,11 +9397,18 @@ static void *pri_dchannel(void *vpri)
3574 pri->pvts[chanpos]->progress = 1;
3575 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3580 case PRI_EVENT_PROCEEDING:
3581 chanpos = pri_find_principle(pri, e->proceeding.channel);
3583 + chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
3584 + if (chanpos < 0) {
3585 + ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n",
3586 + PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
3589 if (!pri->pvts[chanpos]->proceeding) {
3590 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
3592 @@ -9091,6 +9433,7 @@ static void *pri_dchannel(void *vpri)
3593 pri->pvts[chanpos]->proceeding = 1;
3594 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3599 case PRI_EVENT_FACNAME:
3600 @@ -9114,6 +9457,163 @@ static void *pri_dchannel(void *vpri)
3604 + case PRI_EVENT_SUSPEND_REQ:
3605 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3606 + pri_suspend_reject(pri->pri, e->suspend_req.call, "");
3609 + chanpos = pri_find_principle(pri, e->suspend_req.channel);
3610 + if (chanpos < 0) {
3611 + ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
3615 + if (chanpos > -1) {
3616 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
3617 + if (pri->pvts[chanpos]->owner) {
3618 + if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
3619 + struct zt_suspended_call *zpc;
3621 + zpc = malloc(sizeof(struct zt_suspended_call));
3623 + ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
3626 + strncpy(zpc->msn, pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
3627 + strncpy(zpc->callid, e->suspend_req.callid, sizeof(zpc->callid));
3628 + ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
3629 + zpc->next = pri->suspended_calls;
3630 + pri->suspended_calls = zpc;
3631 + snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
3632 + pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
3633 + pri->pvts[chanpos]->call = NULL;
3634 + pri->pvts[chanpos]->tei = -1;
3635 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3637 + pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
3638 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3642 + pri_suspend_reject(pri->pri, e->suspend_req.call, "");
3644 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3647 + case PRI_EVENT_RESUME_REQ:
3648 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3651 + chanpos = pri_find_empty_chan(pri, 1);
3652 + if (chanpos < 0) {
3653 + pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
3654 + ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
3656 + } else if (!pri->pvts[chanpos]) {
3657 + pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
3661 + if (chanpos > -1) {
3662 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
3663 + if (!pri->pvts[chanpos]->owner) {
3664 + struct zt_suspended_call *zpc, *zpcl;
3666 + char extenstr[255], temp[255];
3668 + zpcl = pri->suspended_calls;
3670 + // ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
3671 + if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
3673 + // found a parked call
3674 + snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
3675 + strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
3676 + // strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
3677 + pri->pvts[chanpos]->call = e->resume_req.call;
3679 + if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
3680 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
3681 + // uhh ohh...what shall we do without the bearer cap???
3682 + law = ZT_LAW_ALAW;
3683 + res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
3685 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
3686 + if (!pri->pvts[chanpos]->digital) {
3687 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
3689 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
3692 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
3694 + c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
3696 + pri->pvts[chanpos]->owner = c;
3697 + pri->pvts[chanpos]->call = e->resume_req.call;
3698 + zt_enable_ec(pri->pvts[chanpos]);
3699 + zt_train_ec(pri->pvts[chanpos]);
3701 + ast_log(LOG_ERROR, "unable to start pbx\n");
3705 + zpc->next = zpcl->next;
3710 + pri->suspended_calls = zpcl->next;
3712 + zpcl = pri->suspended_calls;
3716 + snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
3717 + pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
3721 + if (zpcl) zpcl = zpcl->next;
3724 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
3726 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
3728 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3731 + case PRI_EVENT_HOLD_REQ:
3732 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3733 + pri_hold_reject(pri->pri, e->hold_req.call);
3736 + /* holded calls are not implemented yet */
3737 + pri_hold_reject(pri->pri, e->hold_req.call);
3739 + case PRI_EVENT_RETRIEVE_REQ:
3740 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
3741 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
3744 + /* Holded calls are currently not supported */
3745 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
3748 + case PRI_EVENT_DISPLAY_RECEIVED:
3749 + ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
3750 + chanpos = pri_find_principle(pri, e->display.channel);
3751 + if (chanpos < 0) {
3752 + ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
3755 + if (chanpos > -1) {
3756 + if (pri->pvts[chanpos]->owner) {
3757 + // ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
3761 case PRI_EVENT_ANSWER:
3762 chanpos = pri_find_principle(pri, e->answer.channel);
3764 @@ -9126,6 +9626,7 @@ static void *pri_dchannel(void *vpri)
3765 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
3767 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3768 + pri->pvts[chanpos]->tei = e->answer.tei;
3769 /* Now we can do call progress detection */
3771 /* We changed this so it turns on the DSP no matter what... progress or no progress.
3772 @@ -9155,11 +9656,16 @@ static void *pri_dchannel(void *vpri)
3773 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
3774 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
3775 } else if (pri->pvts[chanpos]->confirmanswer) {
3776 - ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
3777 + ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
3778 + enable_dtmf_detect(pri->pvts[chanpos]);
3780 + pri->pvts[chanpos]->dialing = 0;
3781 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
3782 /* Enable echo cancellation if it's not on already */
3783 zt_enable_ec(pri->pvts[chanpos]);
3784 + zt_train_ec(pri->pvts[chanpos]);
3785 + /* stop ignoring inband dtmf */
3786 + enable_dtmf_detect(pri->pvts[chanpos]);
3789 #ifdef SUPPORT_USERUSER
3790 @@ -9216,20 +9722,29 @@ static void *pri_dchannel(void *vpri)
3791 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
3792 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
3794 - pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
3795 + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
3796 pri->pvts[chanpos]->call = NULL;
3797 + pri->pvts[chanpos]->tei = -1;
3799 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
3800 - if (option_verbose > 2)
3801 + if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
3802 + if (option_verbose > 2)
3803 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
3804 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3805 - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
3806 - pri->pvts[chanpos]->resetting = 1;
3808 - if (e->hangup.aoc_units > -1)
3809 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3810 + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
3811 + pri->pvts[chanpos]->resetting = 1;
3814 + if (e->hangup.aoc_units > -1) {
3815 + if (pri->pvts[chanpos]->owner) {
3817 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
3818 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
3820 if (option_verbose > 2)
3821 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
3822 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
3825 #ifdef SUPPORT_USERUSER
3826 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
3827 @@ -9242,8 +9757,9 @@ static void *pri_dchannel(void *vpri)
3829 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3831 - ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
3832 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3833 + ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
3834 + ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
3835 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3839 @@ -9253,15 +9769,23 @@ static void *pri_dchannel(void *vpri)
3840 case PRI_EVENT_HANGUP_REQ:
3841 chanpos = pri_find_principle(pri, e->hangup.channel);
3843 - ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
3844 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3846 + if (pri->nodetype == BRI_NETWORK_PTMP) {
3847 + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
3849 + ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
3850 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3852 + } else if ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing)) {
3853 + /* dont hang up if we want to hear inband call progress */
3854 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
3856 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3857 if (pri->pvts[chanpos]->realcall)
3858 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
3859 else if (pri->pvts[chanpos]->owner) {
3861 + snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
3862 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
3863 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
3864 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
3865 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3866 @@ -9288,16 +9812,34 @@ static void *pri_dchannel(void *vpri)
3867 if (option_verbose > 2)
3868 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
3869 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
3870 + if (e->hangup.aoc_units > -1) {
3871 + if (pri->pvts[chanpos]->owner) {
3873 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
3874 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
3876 + if (option_verbose > 2)
3877 + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
3878 + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
3880 + if (pri->nodetype == BRI_NETWORK_PTMP) {
3881 + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
3882 + pri->pvts[chanpos]->call = NULL;
3883 + pri->pvts[chanpos]->tei = -1;
3886 - pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
3887 + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
3888 pri->pvts[chanpos]->call = NULL;
3889 + pri->pvts[chanpos]->tei = -1;
3891 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
3892 - if (option_verbose > 2)
3893 + if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
3894 + if (option_verbose > 2)
3895 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
3896 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3897 - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
3898 - pri->pvts[chanpos]->resetting = 1;
3899 + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
3900 + pri->pvts[chanpos]->resetting = 1;
3904 #ifdef SUPPORT_USERUSER
3905 @@ -9311,9 +9853,27 @@ static void *pri_dchannel(void *vpri)
3907 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3909 - ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3910 + if (pri->nodetype != BRI_NETWORK_PTMP) {
3911 + ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3913 + ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
3917 + if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
3918 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
3919 + if (e->hangup.aoc_units > -1) {
3921 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
3922 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
3923 + if (option_verbose > 2)
3924 + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
3925 + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
3927 + pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
3928 + ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
3929 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3932 case PRI_EVENT_HANGUP_ACK:
3933 chanpos = pri_find_principle(pri, e->hangup.channel);
3934 @@ -9325,6 +9885,7 @@ static void *pri_dchannel(void *vpri)
3936 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3937 pri->pvts[chanpos]->call = NULL;
3938 + pri->pvts[chanpos]->tei = -1;
3939 pri->pvts[chanpos]->resetting = 0;
3940 if (pri->pvts[chanpos]->owner) {
3941 if (option_verbose > 2)
3942 @@ -9431,10 +9992,22 @@ static void *pri_dchannel(void *vpri)
3943 ast_mutex_lock(&pri->pvts[chanpos]->lock);
3944 switch (e->notify.info) {
3945 case PRI_NOTIFY_REMOTE_HOLD:
3946 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
3947 + ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
3948 + ast_moh_start(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, pri->pvts[chanpos]->mohinterpret);
3950 + ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
3952 f.subclass = AST_CONTROL_HOLD;
3953 zap_queue_frame(pri->pvts[chanpos], &f, pri);
3955 case PRI_NOTIFY_REMOTE_RETRIEVAL:
3956 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
3957 + ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
3958 + ast_moh_stop(ast_bridged_channel(pri->pvts[chanpos]->owner));
3960 + ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
3962 f.subclass = AST_CONTROL_UNHOLD;
3963 zap_queue_frame(pri->pvts[chanpos], &f, pri);
3965 @@ -9442,6 +10015,23 @@ static void *pri_dchannel(void *vpri)
3966 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3969 + case PRI_EVENT_FACILITY:
3970 + if (e->facility.operation == 0x0D) {
3971 + struct ast_channel *owner = pri->pvts[chanpos]->owner;
3973 + ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
3974 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
3977 + ast_string_field_build(owner, call_forward,
3978 + "Local/%s@%s", e->facility.forwardnum,
3981 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
3983 + ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
3987 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
3989 @@ -9503,7 +10093,7 @@ static int start_pri(struct zt_pri *pri)
3993 - pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
3994 + pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
3995 /* Force overlap dial if we're doing GR-303! */
3996 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
3997 pri->overlapdial = 1;
3998 @@ -9571,39 +10161,77 @@ static char *complete_span_5(const char
4000 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
4007 + return RESULT_SHOWUSAGE;
4009 if (!strncasecmp(argv[1], "set", 3)) {
4012 return RESULT_SHOWUSAGE;
4014 - if (ast_strlen_zero(argv[4]))
4015 + if (!argv[4] || ast_strlen_zero(argv[4]))
4016 return RESULT_SHOWUSAGE;
4019 + return RESULT_SHOWUSAGE;
4021 + if (!argv[6] || ast_strlen_zero(argv[6]))
4022 + return RESULT_SHOWUSAGE;
4024 + span = atoi(argv[6]);
4025 + if ((span < 1) && (span > NUM_SPANS)) {
4026 + return RESULT_SUCCESS;
4030 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
4032 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
4033 return RESULT_SUCCESS;
4035 + for (x=0; x < NUM_SPANS; x++) {
4036 + ast_mutex_lock(&pris[x].lock);
4038 - ast_mutex_lock(&pridebugfdlock);
4040 - if (pridebugfd >= 0)
4041 - close(pridebugfd);
4043 - pridebugfd = myfd;
4044 - ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
4046 - ast_mutex_unlock(&pridebugfdlock);
4047 + if (pris[x].span == span) {
4048 + if (pris[x].debugfd >= 0)
4049 + close(pris[x].debugfd);
4050 + pris[x].debugfd = myfd;
4051 + for (d=0; d < NUM_DCHANS; d++) {
4052 + if (pris[x].dchans[d])
4053 + pri_set_debug_fd(pris[x].dchans[d], myfd);
4056 + ast_mutex_unlock(&pris[x].lock);
4059 - ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
4060 + ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
4062 + if (!argv[5] || ast_strlen_zero(argv[5]))
4063 + return RESULT_SHOWUSAGE;
4064 /* Assume it is unset */
4065 - ast_mutex_lock(&pridebugfdlock);
4066 - close(pridebugfd);
4068 - ast_cli(fd, "PRI debug output to file disabled\n");
4069 - ast_mutex_unlock(&pridebugfdlock);
4070 + span = atoi(argv[5]);
4071 + if ((span < 1) && (span > NUM_SPANS)) {
4072 + return RESULT_SUCCESS;
4075 + for (x=0; x < NUM_SPANS; x++) {
4076 + ast_mutex_lock(&pris[x].lock);
4078 + if (pris[x].span == span) {
4079 + if (pris[x].debugfd >= 0)
4080 + close(pris[x].debugfd);
4081 + pris[x].debugfd = -1;
4082 + for (d=0; d < NUM_DCHANS; d++) {
4083 + if (pris[x].dchans[d])
4084 + pri_set_debug_fd(pris[x].dchans[d], -1);
4087 + ast_mutex_unlock(&pris[x].lock);
4090 + ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
4093 return RESULT_SUCCESS;
4094 @@ -9644,6 +10272,7 @@ static int handle_pri_debug(int fd, int
4099 static int handle_pri_no_debug(int fd, int argc, char *argv[])
4102 @@ -9793,10 +10422,6 @@ static int handle_pri_show_debug(int fd,
4106 - ast_mutex_lock(&pridebugfdlock);
4107 - if (pridebugfd >= 0)
4108 - ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
4109 - ast_mutex_unlock(&pridebugfdlock);
4112 ast_cli(fd, "No debug set or no PRI running\n");
4113 @@ -9823,6 +10448,18 @@ static const char pri_show_spans_help[]
4114 "Usage: pri show spans\n"
4115 " Displays PRI Information\n";
4117 +static char bri_debug_help[] =
4118 + "Usage: bri debug span <span>\n"
4119 + " Enables debugging on a given BRI span\n";
4121 +static char bri_no_debug_help[] =
4122 + "Usage: bri no debug span <span>\n"
4123 + " Disables debugging on a given BRI span\n";
4125 +static char bri_really_debug_help[] =
4126 + "Usage: bri intensive debug span <span>\n"
4127 + " Enables debugging down to the Q.921 level\n";
4129 static struct ast_cli_entry zap_pri_cli[] = {
4130 { { "pri", "debug", "span", NULL },
4131 handle_pri_debug, "Enables PRI debugging on a span",
4132 @@ -9847,6 +10484,15 @@ static struct ast_cli_entry zap_pri_cli[
4133 { { "pri", "show", "debug", NULL },
4134 handle_pri_show_debug, "Displays current PRI debug settings" },
4136 + { { "bri", "debug", "span", NULL }, handle_pri_debug,
4137 + "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
4139 + { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
4140 + "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
4142 + { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
4143 + "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
4145 { { "pri", "set", "debug", "file", NULL },
4146 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
4148 @@ -9859,8 +10505,76 @@ static struct ast_cli_entry zap_pri_cli[
4152 +static char *zapCD_tdesc = "Call Deflection";
4153 +static char *zapCD_app = "zapCD";
4154 +static char *zapCD_synopsis = "Call Deflection";
4156 +static int app_zapCD(struct ast_channel *chan, void *data)
4158 + struct zt_pvt *p = chan->tech_pvt;
4160 + if((!p->pri) || (!p->pri->pri)) {
4165 + ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
4168 + return pri_deflect(p->pri->pri, p->call, data);
4171 +static char *zapInband_tdesc = "Inband Call Progress (pre-answer)";
4172 +static char *zapInband_app = "zapInband";
4173 +static char *zapInband_synopsis = "Inband Call Progress";
4175 +static int app_zapInband(struct ast_channel *chan, void *data)
4177 + struct zt_pvt *p = chan->tech_pvt;
4179 + return pri_acknowledge(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1);
4182 #endif /* HAVE_PRI */
4184 +static int app_zapEC(struct ast_channel *chan, void *data)
4187 + struct zt_pvt *p = NULL;
4190 + ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
4192 + if (chan && !strcasecmp("ZAP",chan->tech->type)) {
4193 + p = chan->tech_pvt;
4194 + if (!p) return res;
4195 + if (!strcasecmp("on",(char *)data)) {
4198 + if (option_verbose > 3) {
4199 + ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
4201 + } else if (!strcasecmp("off",(char *)data)) {
4204 + if (option_verbose > 3) {
4205 + ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
4208 + ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
4211 + ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
4218 +static char *zapEC_tdesc = "Enable/disable Echo cancelation";
4219 +static char *zapEC_app = "zapEC";
4220 +static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
4222 static int zap_destroy_channel(int fd, int argc, char **argv)
4225 @@ -10441,8 +11155,11 @@ static int __unload_module(void)
4227 ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
4228 ast_unregister_application(zap_send_keypad_facility_app);
4229 + ast_unregister_application(zapCD_app);
4230 + ast_unregister_application(zapInband_app);
4232 ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
4233 + ast_unregister_application(zapEC_app);
4234 ast_manager_unregister( "ZapDialOffhook" );
4235 ast_manager_unregister( "ZapHangup" );
4236 ast_manager_unregister( "ZapTransfer" );
4237 @@ -10944,6 +11661,22 @@ static int process_zap(struct zt_chan_co
4238 confp->chan.sig = SIG_GR303FXSKS;
4239 confp->chan.radio = 0;
4240 confp->pri.nodetype = PRI_CPE;
4241 + } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
4242 + confp->chan.radio = 0;
4243 + confp->chan.sig = SIG_PRI;
4244 + confp->pri.nodetype = BRI_NETWORK_PTMP;
4245 + } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
4246 + confp->chan.sig = SIG_PRI;
4247 + confp->chan.radio = 0;
4248 + confp->pri.nodetype = BRI_CPE_PTMP;
4249 + } else if (!strcasecmp(v->value, "bri_net")) {
4250 + confp->chan.radio = 0;
4251 + confp->chan.sig = SIG_PRI;
4252 + confp->pri.nodetype = BRI_NETWORK;
4253 + } else if (!strcasecmp(v->value, "bri_cpe")) {
4254 + confp->chan.sig = SIG_PRI;
4255 + confp->chan.radio = 0;
4256 + confp->pri.nodetype = BRI_CPE;
4259 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
4260 @@ -11056,9 +11789,21 @@ static int process_zap(struct zt_chan_co
4261 confp->chan.priindication_oob = 1;
4262 else if (!strcasecmp(v->value, "inband"))
4263 confp->chan.priindication_oob = 0;
4264 + else if (!strcasecmp(v->value, "passthrough"))
4265 + confp->chan.priindication_oob = 2;
4267 - ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
4268 + ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband', 'outofband' or 'passthrough' at line %d\n",
4269 v->value, v->lineno);
4270 + } else if (!strcasecmp(v->name, "pritransfer")) {
4271 + if (!strcasecmp(v->value, "no"))
4272 + confp->chan.pritransfer = 0;
4273 + else if (!strcasecmp(v->value, "ect"))
4274 + confp->chan.pritransfer = 1;
4275 + else if (!strcasecmp(v->value, "hangup"))
4276 + confp->chan.pritransfer = 2;
4278 + ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
4279 + v->value, v->lineno);
4280 } else if (!strcasecmp(v->name, "priexclusive")) {
4281 confp->chan.priexclusive = ast_true(v->value);
4282 } else if (!strcasecmp(v->name, "internationalprefix")) {
4283 @@ -11071,6 +11816,10 @@ static int process_zap(struct zt_chan_co
4284 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
4285 } else if (!strcasecmp(v->name, "unknownprefix")) {
4286 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
4287 + } else if (!strcasecmp(v->name, "nocid")) {
4288 + ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
4289 + } else if (!strcasecmp(v->name, "withheldcid")) {
4290 + ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
4291 } else if (!strcasecmp(v->name, "resetinterval")) {
4292 if (!strcasecmp(v->value, "never"))
4293 confp->pri.resetinterval = -1;
4294 @@ -11087,6 +11836,8 @@ static int process_zap(struct zt_chan_co
4295 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
4296 } else if (!strcasecmp(v->name, "idledial")) {
4297 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
4298 + } else if (!strcasecmp(v->name, "pritrustusercid")) {
4299 + confp->pri.usercid = ast_true(v->value);
4300 } else if (!strcasecmp(v->name, "overlapdial")) {
4301 confp->pri.overlapdial = ast_true(v->value);
4302 } else if (!strcasecmp(v->name, "pritimer")) {
4303 @@ -11389,6 +12140,7 @@ static int setup_zap(int reload)
4306 for (x = 0; x < NUM_SPANS; x++) {
4307 + pris[x].debugfd = -1;
4308 if (pris[x].pvts[0]) {
4309 if (start_pri(pris + x)) {
4310 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
4311 @@ -11436,7 +12188,10 @@ static int load_module(void)
4312 ast_string_field_init(&inuse, 16);
4313 ast_string_field_set(&inuse, name, "GR-303InUse");
4314 ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
4315 + ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
4316 + ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
4318 + ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
4319 ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
4321 memset(round_robin, 0, sizeof(round_robin));
4322 @@ -11470,6 +12225,7 @@ static int zt_sendtext(struct ast_channe
4327 index = zt_get_index(c, p, 0);
4329 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
4330 --- a/configs/zapata.conf.sample
4331 +++ b/configs/zapata.conf.sample
4332 @@ -123,9 +123,20 @@ switchtype=national
4334 ; outofband: Signal Busy/Congestion out of band with RELEASE/DISCONNECT
4335 ; inband: Signal Busy/Congestion using in-band tones
4336 +; passthrough: Listen to the telco
4338 ; priindication = outofband
4340 +; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
4342 +; Configure how transfers are initiated. ECT should be preferred
4344 +; no: no transfers allowed (results in hangup)
4345 +; ect: use ECT (facility)
4346 +; hangup: transfer on hangup (if your phones dont support ECT)
4348 +; pritransfer = ect
4350 ; If you need to override the existing channels selection routine and force all
4351 ; PRI channels to be marked as exclusively selected, set this to yes.
4352 ; priexclusive = yes
4353 Change the ABI of ast_channel_tech to add a new function, send_message that is
4354 to be used by channels wanting to send text messages with a destination number
4357 --- a/include/asterisk/channel.h
4358 +++ b/include/asterisk/channel.h
4359 @@ -247,6 +247,11 @@ struct ast_channel_tech {
4360 /*! \brief Display or transmit text */
4361 int (* const send_text)(struct ast_channel *chan, const char *text);
4363 +#if 0 /* we (Debian) disable that addition because of ABI breakage */
4364 + /*! \brief send a message */
4365 + int (* const send_message)(struct ast_channel *chan, const char *dest, const char *text, int ispdu);
4368 /*! \brief Display or send an image */
4369 int (* const send_image)(struct ast_channel *chan, struct ast_frame *frame);
4371 @@ -689,6 +694,16 @@ struct ast_channel *ast_request_and_dial
4373 struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname, struct outgoing_helper *oh);
4375 +/*! \brief "Requests" a channel for sending a message
4376 + * \param type type of channel to request
4377 + * \param data data to pass to the channel requester
4378 + * \param status status
4379 + * Request a channel of a given type, with data as optional information used
4380 + * by the low level module
4381 + * \return Returns 0 on success, -1 on failure.
4383 +int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu);
4385 /*!\brief Register a channel technology (a new channel driver)
4386 * Called by a channel module to register the kind of channels it supports.
4387 * \param tech Structure defining channel technology or "type"
4388 @@ -910,6 +925,16 @@ int ast_set_write_format(struct ast_chan
4390 int ast_sendtext(struct ast_channel *chan, const char *text);
4392 +/*! \brief Sends message to a channel
4393 + * Write text to a display on a channel
4394 + * \param chan channel to act upon
4395 + * \param dest destination number/user
4396 + * \param text string of text to send on the channel
4397 + * \param ispdu message is in PDU format
4398 + * \return Returns 0 on success, -1 on failure
4400 +int ast_sendmessage(struct ast_channel *chan, const char *dest, const char *text, int ispdu);
4402 /*! \brief Receives a text character from a channel
4403 * \param chan channel to act upon
4404 * \param timeout timeout in milliseconds (0 for infinite wait)
4405 --- a/main/channel.c
4406 +++ b/main/channel.c
4407 @@ -2472,6 +2472,21 @@ int ast_sendtext(struct ast_channel *cha
4411 +int ast_sendmessage(struct ast_channel *chan, const char *dest, const char *text, int ispdu)
4414 + /* Stop if we're a zombie or need a soft hangup */
4415 + if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))
4417 + CHECK_BLOCKING(chan);
4418 +#if 0 /* we (Debian) disable that addition because of ABI breakage */
4419 + if (chan->tech->send_message)
4420 + res = chan->tech->send_message(chan, dest, text, ispdu);
4422 + ast_clear_flag(chan, AST_FLAG_BLOCKING);
4426 int ast_senddigit_begin(struct ast_channel *chan, char digit)
4428 /* Device does not support DTMF tones, lets fake
4429 @@ -4515,6 +4530,25 @@ void ast_channel_stop_silence_generator(
4433 +int ast_send_message(const char *type, void *data, char *to, char *from, char *message, int ispdu) {
4434 + struct ast_channel *chan = NULL;
4438 + chan = ast_request(type, AST_FORMAT_SLINEAR, data, &status);
4441 + ast_set_callerid(chan, from, from, from);
4443 + res = ast_sendmessage(chan, to, message, ispdu);
4444 + /* XXX what about message CDRs ??? XXX */
4452 /*! \ brief Convert channel reloadreason (ENUM) to text string for manager event */
4453 const char *channelreloadreason2txt(enum channelreloadreason reason)
4455 --- a/main/manager.c
4456 +++ b/main/manager.c
4458 * the project provides a web site, mailing lists and IRC
4459 * channels for your use.
4461 + * Copyright (C) 2003-2004, Junghanns.NET Gmbh
4462 + * Klaus-Peter Junghanns <kpj@junghanns.net>
4464 * This program is free software, distributed under the terms of
4465 * the GNU General Public License Version 2. See the LICENSE file
4466 * at the top of the source tree.
4467 @@ -1427,6 +1430,49 @@ static int action_hangup(struct mansessi
4471 +static char mandescr_message[] =
4472 +"Description: Send a message\n"
4474 +" Channel: The destination channel(e.g. SIP/phone1)\n"
4476 +" Message: The message to send\n";
4478 +static int action_message(struct mansession *s, const struct message *m)
4480 + const char *name = astman_get_header(m, "Channel");
4481 + const char *from = astman_get_header(m, "From");
4482 + const char *message = astman_get_header(m, "Message");
4483 + const char *pdu = astman_get_header(m, "PDU");
4485 + char *tech, *data;
4487 + if (ast_strlen_zero(name) || (ast_strlen_zero(message) && ast_strlen_zero(pdu))) {
4488 + astman_send_error(s, m, "No channel or message/PDU specified");
4491 + ast_copy_string(tmp, name, sizeof(tmp));
4493 + data = strchr(tmp, '/');
4495 + astman_send_error(s, m, "Invalid channel\n");
4500 + if (ast_strlen_zero(pdu)) {
4501 + res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)message, 0);
4503 + res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)pdu, 1);
4507 + astman_send_error(s, m, "Error sending message");
4510 + astman_send_ack(s, m, "Message sent");
4514 static char mandescr_setvar[] =
4515 "Description: Set a global or local channel variable.\n"
4516 "Variables: (Names marked with * are required)\n"
4517 @@ -2853,6 +2899,7 @@ int init_manager(void)
4518 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
4519 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
4520 ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
4521 + ast_manager_register2("Message", EVENT_FLAG_CALL, action_message, "Send Message", mandescr_message);
4522 ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
4523 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
4524 ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
4525 --- a/pbx/pbx_spool.c
4526 +++ b/pbx/pbx_spool.c
4527 @@ -87,6 +87,10 @@ struct outgoing {
4532 + char message[256];
4535 /* If extension/context/priority */
4538 @@ -181,6 +185,10 @@ static int apply_outgoing(struct outgoin
4539 ast_copy_string(o->app, c, sizeof(o->app));
4540 } else if (!strcasecmp(buf, "data")) {
4541 ast_copy_string(o->data, c, sizeof(o->data));
4542 + } else if (!strcasecmp(buf, "message")) {
4543 + strncpy(o->message, c, sizeof(o->message) - 1);
4544 + } else if (!strcasecmp(buf, "pdu")) {
4545 + strncpy(o->pdu, c, sizeof(o->pdu) - 1);
4546 } else if (!strcasecmp(buf, "maxretries")) {
4547 if (sscanf(c, "%d", &o->maxretries) != 1) {
4548 ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn);
4549 @@ -241,8 +249,8 @@ static int apply_outgoing(struct outgoin
4552 ast_copy_string(o->fn, fn, sizeof(o->fn));
4553 - if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) {
4554 - ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
4555 + if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || ((ast_strlen_zero(o->app) && ast_strlen_zero(o->exten) && ast_strlen_zero(o->message) && ast_strlen_zero(o->pdu)))) {
4556 + ast_log(LOG_WARNING, "At least one of app or extension (or keyword message/pdu)must be specified, along with tech and dest in file %s\n", fn);
4560 @@ -332,6 +340,14 @@ static void *attempt_thread(void *data)
4561 if (option_verbose > 2)
4562 ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
4563 res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
4564 + } else if (!ast_strlen_zero(o->message)) {
4565 + if (option_verbose > 2)
4566 + ast_verbose(VERBOSE_PREFIX_3 "Attempting to send message on %s/%s (Retry %d)\n", o->tech, o->dest, o->retries);
4567 + res = ast_send_message(o->tech, o->dest, o->dest, (ast_strlen_zero(o->cid_name) ? o->cid_num : o->cid_name), o->message, 0);
4568 + } else if (!ast_strlen_zero(o->pdu)) {
4569 + if (option_verbose > 2)
4570 + ast_verbose(VERBOSE_PREFIX_3 "Attempting to send message in PDU format on %s/%s (Retry %d)\n", o->tech, o->dest, o->retries);
4571 + res = ast_send_message(o->tech, o->dest, o->dest, (ast_strlen_zero(o->cid_name) ? o->cid_num : o->cid_name), o->pdu, 1);
4573 if (option_verbose > 2)
4574 ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
4575 @@ -348,9 +364,14 @@ static void *attempt_thread(void *data)
4576 safe_append(o, time(NULL), "EndRetry");
4579 + if (!ast_strlen_zero(o->message)) {
4580 + if (option_verbose > 2)
4581 + ast_verbose(VERBOSE_PREFIX_2 "Message sent to %s/%s\n", o->tech, o->dest);
4583 ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
4584 ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
4585 - remove_from_queue(o, "Completed");
4587 + remove_from_queue(o, "Completed");
4591 --- a/include/asterisk/monitor.h
4592 +++ b/include/asterisk/monitor.h
4593 @@ -38,6 +38,8 @@ struct ast_channel_monitor {
4594 char write_filename[FILENAME_MAX];
4595 char filename_base[FILENAME_MAX];
4596 int filename_changed;
4597 + char target_url[FILENAME_MAX];
4598 + char target_script[FILENAME_MAX];
4601 enum AST_MONITORING_STATE state;
4602 @@ -46,7 +48,7 @@ struct ast_channel_monitor {
4604 /* Start monitoring a channel */
4605 int ast_monitor_start(struct ast_channel *chan, const char *format_spec,
4606 - const char *fname_base, int need_lock );
4607 + const char *fname_base, const char *target_url, const char *target_script, int need_lock );
4609 /* Stop monitoring a channel */
4610 int ast_monitor_stop(struct ast_channel *chan, int need_lock);
4611 --- a/res/res_monitor.c
4612 +++ b/res/res_monitor.c
4613 @@ -130,7 +130,7 @@ static int ast_monitor_set_state(struct
4615 /* Start monitoring a channel */
4616 int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
4617 - const char *fname_base, int need_lock)
4618 + const char *fname_base, const char *target_url, const char *target_script, int need_lock)
4622 @@ -154,6 +154,11 @@ int ast_monitor_start( struct ast_channe
4627 + ast_copy_string(monitor->target_url, target_url, sizeof(monitor->target_url));
4628 + if (target_script)
4629 + ast_copy_string(monitor->target_script, target_script, sizeof(monitor->target_script));
4631 /* Determine file names */
4632 if (!ast_strlen_zero(fname_base)) {
4633 int directory = strchr(fname_base, '/') ? 1 : 0;
4634 @@ -297,6 +302,8 @@ int ast_monitor_stop(struct ast_channel
4635 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
4640 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
4641 char *name = chan->monitor->filename_base;
4642 int directory = strchr(name, '/') ? 1 : 0;
4643 @@ -325,8 +332,13 @@ int ast_monitor_stop(struct ast_channel
4644 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name); /* remove legs when done mixing */
4645 ast_copy_string(tmp, tmp2, sizeof(tmp));
4647 - ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
4648 - if (ast_safe_system(tmp) == -1)
4649 + if (!ast_strlen_zero(chan->monitor->target_script) && !ast_strlen_zero(chan->monitor->target_url)) {
4650 + snprintf(tmp3,sizeof(tmp3), "( %s& nice -19 %s \"%s/%s.%s\" \"%s\" ) &",tmp, chan->monitor->target_script , dir, name, format, chan->monitor->target_url);
4651 + ast_copy_string(tmp, tmp3, sizeof(tmp));
4653 + ast_log(LOG_NOTICE,"monitor executing %s\n",tmp);
4654 + result = ast_safe_system(tmp);
4656 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
4659 @@ -467,7 +479,7 @@ static int start_monitor_exec(struct ast
4663 - res = ast_monitor_start(chan, format, fname_base, 1);
4664 + res = ast_monitor_start(chan, format, fname_base, NULL, NULL, 1);
4666 res = ast_monitor_change_fname(chan, fname_base, 1);
4667 ast_monitor_setjoinfiles(chan, joinfiles);
4668 @@ -506,6 +518,8 @@ static int start_monitor_action(struct m
4669 const char *fname = astman_get_header(m, "File");
4670 const char *format = astman_get_header(m, "Format");
4671 const char *mix = astman_get_header(m, "Mix");
4672 + const char *target_url = astman_get_header(m, "TargetURL");
4673 + const char *target_script = astman_get_header(m, "TargetScript");
4676 if (ast_strlen_zero(name)) {
4677 @@ -530,7 +544,7 @@ static int start_monitor_action(struct m
4681 - if (ast_monitor_start(c, format, fname, 1)) {
4682 + if (ast_monitor_start(c, format, fname, target_url, target_script, 1)) {
4683 if (ast_monitor_change_fname(c, fname, 1)) {
4684 astman_send_error(s, m, "Could not start monitoring channel");
4685 ast_channel_unlock(c);
4686 --- a/apps/app_queue.c
4687 +++ b/apps/app_queue.c
4688 @@ -2891,13 +2891,13 @@ static int try_calling(struct queue_ent
4691 if (monitorfilename)
4692 - ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
4693 + ast_monitor_start(which, qe->parent->monfmt, monitorfilename, NULL, NULL, 1 );
4694 else if (qe->chan->cdr)
4695 - ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
4696 + ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, NULL, NULL, 1 );
4698 /* Last ditch effort -- no CDR, make up something */
4699 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
4700 - ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
4701 + ast_monitor_start(which, qe->parent->monfmt, tmpid, NULL, NULL, 1 );
4703 if (qe->parent->monjoin)
4704 ast_monitor_setjoinfiles(which, 1);
4705 --- a/channels/chan_agent.c
4706 +++ b/channels/chan_agent.c
4707 @@ -419,7 +419,7 @@ static int __agent_start_monitoring(stru
4708 if ((pointer = strchr(filename, '.')))
4710 snprintf(tmp, sizeof(tmp), "%s%s", savecallsin, filename);
4711 - ast_monitor_start(ast, recordformat, tmp, needlock);
4712 + ast_monitor_start(ast, recordformat, tmp, NULL, NULL, needlock);
4713 ast_monitor_setjoinfiles(ast, 1);
4714 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix, filename, recordformatext);
4716 --- a/include/asterisk/devicestate.h
4717 +++ b/include/asterisk/devicestate.h
4718 @@ -47,7 +47,7 @@ extern "C" {
4719 #define AST_DEVICE_ONHOLD 8
4721 /*! \brief Devicestate watcher call back */
4722 -typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
4723 +typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data, char *cid_num, char *cid_name);
4725 /*! \brief Devicestate provider call back */
4726 typedef int (*ast_devstate_prov_cb_type)(const char *data);
4727 @@ -92,7 +92,7 @@ int ast_device_state_changed(const char
4728 * callbacks for the changed extensions
4729 * Returns 0 on success, -1 on failure
4731 -int ast_device_state_changed_literal(const char *device);
4732 +int ast_device_state_changed_literal(const char *device, const char *cid_num, const char *cid_name);
4734 /*! \brief Registers a device state change callback
4735 * \param callback Callback
4736 --- a/main/devicestate.c
4737 +++ b/main/devicestate.c
4738 @@ -78,6 +78,8 @@ static AST_LIST_HEAD_STATIC(devstate_cbs
4740 struct state_change {
4741 AST_LIST_ENTRY(state_change) list;
4742 + char cid_num[AST_MAX_EXTENSION];
4743 + char cid_name[AST_MAX_EXTENSION];
4747 @@ -277,7 +279,7 @@ void ast_devstate_del(ast_devstate_cb_ty
4748 /*! \brief Notify callback watchers of change, and notify PBX core for hint updates
4749 Normally executed within a separate thread
4751 -static void do_state_change(const char *device)
4752 +static void do_state_change(const char *device, char *cid_num, char *cid_name)
4755 struct devstate_cb *devcb;
4756 @@ -288,13 +290,13 @@ static void do_state_change(const char *
4758 AST_LIST_LOCK(&devstate_cbs);
4759 AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
4760 - devcb->callback(device, state, devcb->data);
4761 + devcb->callback(device, state, devcb->data, cid_num, cid_name);
4762 AST_LIST_UNLOCK(&devstate_cbs);
4764 - ast_hint_state_changed(device);
4765 + ast_hint_state_changed(device, cid_num, cid_name);
4768 -static int __ast_device_state_changed_literal(char *buf, int norecurse)
4769 +static int __ast_device_state_changed_literal(char *buf, int norecurse, char *cid_num, char *cid_name)
4772 struct state_change *change;
4773 @@ -308,10 +310,16 @@ static int __ast_device_state_changed_li
4774 if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
4775 /* we could not allocate a change struct, or */
4776 /* there is no background thread, so process the change now */
4777 - do_state_change(device);
4778 + do_state_change(device, cid_num, cid_name);
4780 /* queue the change */
4781 strcpy(change->device, device);
4782 + if (cid_num && (!ast_strlen_zero(cid_num))) {
4783 + strncpy(change->cid_num, cid_num, sizeof(change->cid_num) - 1);
4785 + if (cid_name && (!ast_strlen_zero(cid_name))) {
4786 + strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
4788 AST_LIST_LOCK(&state_changes);
4789 AST_LIST_INSERT_TAIL(&state_changes, change, list);
4790 if (AST_LIST_FIRST(&state_changes) == change)
4791 @@ -329,17 +337,23 @@ static int __ast_device_state_changed_li
4793 if (!norecurse && (tmp = strrchr(device, '-'))) {
4795 - __ast_device_state_changed_literal(device, 1);
4796 + __ast_device_state_changed_literal(device, 1, cid_num, cid_name);
4802 -int ast_device_state_changed_literal(const char *dev)
4803 +int ast_device_state_changed_literal(const char *dev, const char *cid_num, const char *cid_name)
4806 + char *buf2 = NULL;
4807 + char *buf3 = NULL;
4808 buf = ast_strdupa(dev);
4809 - return __ast_device_state_changed_literal(buf, 0);
4811 + buf2 = ast_strdupa(cid_num);
4813 + buf3 = ast_strdupa(cid_name);
4814 + return __ast_device_state_changed_literal(buf, 0, buf2, buf3);
4817 /*! \brief Accept change notification, add it to change queue */
4818 @@ -351,7 +365,7 @@ int ast_device_state_changed(const char
4820 vsnprintf(buf, sizeof(buf), fmt, ap);
4822 - return __ast_device_state_changed_literal(buf, 0);
4823 + return __ast_device_state_changed_literal(buf, 0, NULL, NULL);
4826 /*! \brief Go through the dev state change queue and update changes in the dev state thread */
4827 @@ -366,7 +380,7 @@ static void *do_devstate_changes(void *d
4829 /* we got an entry, so unlock the list while we process it */
4830 AST_LIST_UNLOCK(&state_changes);
4831 - do_state_change(cur->device);
4832 + do_state_change(cur->device, cur->cid_num, cur->cid_name);
4834 AST_LIST_LOCK(&state_changes);
4836 --- a/include/asterisk/channel.h
4837 +++ b/include/asterisk/channel.h
4838 @@ -613,8 +613,13 @@ int ast_channel_datastore_remove(struct
4839 /*! \brief Find a datastore on a channel */
4840 struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, char *uid);
4842 +extern ast_mutex_t uniquelock;
4844 +/*! \brief Change the state of a channel and the callerid of the calling channel*/
4845 +int ast_setstate_and_callerid(struct ast_channel *chan, enum ast_channel_state state, char *cid_num, char *cid_name);
4847 /*! \brief Change the state of a channel */
4848 -int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
4849 +int ast_setstate(struct ast_channel *chan, enum ast_channel_state state);
4851 /*! \brief Create a channel structure
4852 \return Returns NULL on failure to allocate.
4853 --- a/main/channel.c
4854 +++ b/main/channel.c
4855 @@ -1261,7 +1261,7 @@ void ast_channel_free(struct ast_channel
4857 AST_LIST_UNLOCK(&channels);
4859 - ast_device_state_changed_literal(name);
4860 + ast_device_state_changed_literal(name, NULL, NULL);
4863 struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, char *uid)
4864 @@ -3673,7 +3673,7 @@ void ast_set_callerid(struct ast_channel
4865 ast_channel_unlock(chan);
4868 -int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
4869 +int ast_setstate_and_callerid(struct ast_channel *chan, enum ast_channel_state state, char *cid_num, char *cid_name)
4871 int oldstate = chan->_state;
4873 @@ -3681,7 +3681,7 @@ int ast_setstate(struct ast_channel *cha
4876 chan->_state = state;
4877 - ast_device_state_changed_literal(chan->name);
4878 + ast_device_state_changed_literal(chan->name, cid_num, cid_name);
4879 /* setstate used to conditionally report Newchannel; this is no more */
4880 manager_event(EVENT_FLAG_CALL,
4882 @@ -3698,6 +3698,11 @@ int ast_setstate(struct ast_channel *cha
4886 +int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
4888 + return ast_setstate_and_callerid(chan, state, NULL, NULL);
4891 /*! \brief Find bridged channel */
4892 struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
4894 --- a/include/asterisk/pbx.h
4895 +++ b/include/asterisk/pbx.h
4896 @@ -63,7 +63,7 @@ struct ast_ignorepat;
4899 /*! \brief Typedef for devicestate and hint callbacks */
4900 -typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
4901 +typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data, char *cid_num, char *cid_name);
4903 /*! \brief Data structure associated with a custom dialplan function */
4904 struct ast_custom_function {
4905 @@ -875,7 +875,7 @@ int ast_func_read(struct ast_channel *ch
4907 int ast_func_write(struct ast_channel *chan, char *function, const char *value);
4909 -void ast_hint_state_changed(const char *device);
4910 +void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name);
4912 #if defined(__cplusplus) || defined(c_plusplus)
4916 @@ -2022,7 +2022,7 @@ int ast_extension_state(struct ast_chann
4917 return ast_extension_state2(e); /* Check all devices in the hint */
4920 -void ast_hint_state_changed(const char *device)
4921 +void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
4923 struct ast_hint *hint;
4925 @@ -2053,11 +2053,11 @@ void ast_hint_state_changed(const char *
4927 /* For general callbacks */
4928 for (cblist = statecbs; cblist; cblist = cblist->next)
4929 - cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
4930 + cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
4932 /* For extension callbacks */
4933 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
4934 - cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
4935 + cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
4937 hint->laststate = state; /* record we saw the change */
4939 @@ -2252,7 +2252,7 @@ static int ast_remove_hint(struct ast_ex
4940 /* Notify with -1 and remove all callbacks */
4942 cblist = cblist->next;
4943 - cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
4944 + cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
4947 hint->callbacks = NULL;
4948 @@ -4021,7 +4021,7 @@ void ast_merge_contexts_and_delete(struc
4951 thiscb = thiscb->next;
4952 - prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
4953 + prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
4957 --- a/channels/chan_sip.c
4958 +++ b/channels/chan_sip.c
4959 @@ -1342,7 +1342,7 @@ static void ast_quiet_chan(struct ast_ch
4960 static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
4962 /*--- Device monitoring and Device/extension state handling */
4963 -static int cb_extensionstate(char *context, char* exten, int state, void *data);
4964 +static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name);
4965 static int sip_devicestate(void *data);
4966 static int sip_poke_noanswer(const void *data);
4967 static int sip_poke_peer(struct sip_peer *peer);
4968 @@ -8593,7 +8593,7 @@ static void sip_peer_hold(struct sip_pvt
4969 /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
4970 \note If you add an "hint" priority to the extension in the dial plan,
4971 you will get notifications on device state changes */
4972 -static int cb_extensionstate(char *context, char* exten, int state, void *data)
4973 +static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
4975 struct sip_pvt *p = data;
4977 @@ -12783,7 +12783,7 @@ static void handle_response(struct sip_p
4978 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
4979 /* Ready to send the next state we have on queue */
4980 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
4981 - cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
4982 + cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p, NULL, NULL);
4985 } else if (sipmethod == SIP_REGISTER)
4986 @@ -13036,7 +13036,7 @@ static void handle_response(struct sip_p
4987 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
4988 /* Ready to send the next state we have on queue */
4989 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
4990 - cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
4991 + cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p, NULL, NULL);
4994 } else if (sipmethod == SIP_BYE)
4995 --- a/apps/app_queue.c
4996 +++ b/apps/app_queue.c
4997 @@ -721,7 +721,7 @@ static void *device_state_thread(void *d
5000 /*! \brief Producer of the statechange queue */
5001 -static int statechange_queue(const char *dev, int state, void *ign)
5002 +static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
5004 struct statechange *sc;
5006 --- a/include/asterisk/manager.h
5007 +++ b/include/asterisk/manager.h
5009 #define EVENT_FLAG_AGENT (1 << 5) /* Ability to read/set agent info */
5010 #define EVENT_FLAG_USER (1 << 6) /* Ability to read/set user info */
5011 #define EVENT_FLAG_CONFIG (1 << 7) /* Ability to modify configurations */
5012 +#define EVENT_FLAG_EXTENSIONSTATUS (1 << 8) /* ExtensionStatus events */
5014 /* Export manager structures */
5015 #define AST_MAX_MANHEADERS 128
5016 --- a/main/manager.c
5017 +++ b/main/manager.c
5018 @@ -129,6 +129,7 @@ static struct permalias {
5019 { EVENT_FLAG_AGENT, "agent" },
5020 { EVENT_FLAG_USER, "user" },
5021 { EVENT_FLAG_CONFIG, "config" },
5022 + { EVENT_FLAG_EXTENSIONSTATUS, "extensionstatus" },
5026 @@ -2551,10 +2552,12 @@ int ast_manager_unregister(char *action)
5030 -static int manager_state_cb(char *context, char *exten, int state, void *data)
5031 +static int manager_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
5033 + char hint[256] = "";
5034 + ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
5035 /* Notify managers of change */
5036 - manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
5037 + manager_event(EVENT_FLAG_EXTENSIONSTATUS, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\nCallerID: \"%s\" <%s>\r\nHint: %s\r\n", exten, context, state, cid_num, cid_name, hint);
5041 --- a/apps/app_devstate.c
5042 +++ b/apps/app_devstate.c
5043 @@ -50,7 +50,7 @@ static struct ast_cli_entry cli_dev_sta
5044 static int devstate_cli(int fd, int argc, char *argv[])
5048 + if ((argc != 3) && (argc != 4) && (argc != 5))
5049 return RESULT_SHOWUSAGE;
5051 if (ast_db_put("DEVSTATES", argv[1], argv[2]))
5052 @@ -58,7 +58,15 @@ static int devstate_cli(int fd, int argc
5053 ast_log(LOG_DEBUG, "ast_db_put failed\n");
5055 snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
5056 - ast_device_state_changed_literal(devName);
5058 + ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
5059 + ast_device_state_changed_literal(devName, argv[3], NULL);
5060 + } else if (argc == 5) {
5061 + ast_log(LOG_NOTICE, "devname %s cid %s cidname %s\n", devName, argv[3], argv[4]);
5062 + ast_device_state_changed_literal(devName, argv[3], argv[4]);
5064 + ast_device_state_changed_literal(devName, NULL, NULL);
5066 return RESULT_SUCCESS;
5069 @@ -93,7 +101,7 @@ static int devstate_exec(struct ast_chan
5072 snprintf(devName, sizeof(devName), "DS/%s", device);
5073 - ast_device_state_changed_literal(devName);
5074 + ast_device_state_changed_literal(devName, NULL, NULL);
5076 ast_module_user_remove(u);
5078 @@ -150,6 +158,8 @@ static int action_devstate(struct manses
5079 const char *devstate = astman_get_header(m, "Devstate");
5080 const char *value = astman_get_header(m, "Value");
5081 const char *id = astman_get_header(m,"ActionID");
5082 + const char *cid_num = astman_get_header(m, "CallerID");
5083 + const char *cid_name = astman_get_header(m, "CallerIDName");
5085 char idText[256] = "";
5087 @@ -166,7 +176,7 @@ static int action_devstate(struct manses
5089 if (!ast_db_put("DEVSTATES", devstate, (char *)value)) {
5090 snprintf(devName, sizeof(devName), "DS/%s", devstate);
5091 - ast_device_state_changed_literal(devName);
5092 + ast_device_state_changed_literal(devName, cid_num, cid_name);
5093 astman_append(s, "Response: Success\r\n%s\r\n", idText);
5095 ast_log(LOG_DEBUG, "ast_db_put failed\n");
5096 --- a/res/res_esel.c
5097 +++ b/res/res_esel.c
5098 @@ -51,6 +51,8 @@ typedef struct esel_extension_state {
5099 char context[AST_MAX_EXTENSION];
5100 char exten[AST_MAX_EXTENSION];
5102 + char cid_num[AST_MAX_EXTENSION];
5103 + char cid_name[AST_MAX_EXTENSION];
5104 char devstate[AST_MAX_EXTENSION];
5105 struct esel_extension_state *next;
5106 struct esel_extension_state *prev;
5107 @@ -93,7 +95,7 @@ typedef struct esel_pvt {
5109 static struct esel_pvt *donkeys = NULL;
5111 -static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data) {
5112 +static int esel_queue_extension_state(struct esel_queue *queue, char *context, char *exten, int state, void *data, char *cid_num, char *cid_name) {
5113 struct esel_extension_state *exstate = NULL;
5115 exstate = malloc(sizeof(struct esel_extension_state));
5116 @@ -115,6 +117,8 @@ static int esel_queue_extension_state(st
5118 ast_copy_string(exstate->exten, exten, sizeof(exstate->exten));
5119 ast_copy_string(exstate->context, context, sizeof(exstate->context));
5120 + ast_copy_string(exstate->cid_num, cid_num, sizeof(exstate->cid_num));
5121 + ast_copy_string(exstate->cid_name, cid_name, sizeof(exstate->cid_name));
5122 exstate->state = state;
5125 @@ -161,7 +165,7 @@ static void esel_export_to_remote(struct
5128 memset(msg, 0x0, sizeof(msg));
5129 - snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state));
5130 + snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\nCallerID: %s\r\nCallerIDName: %s\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state), exstate->cid_num, exstate->cid_name);
5131 sent = send(esel->sockfd, msg, strlen(msg), 0);
5133 esel->connected = 0;
5134 @@ -250,13 +254,13 @@ static void *do_esel_thread(void *data)
5138 -static int esel_state_cb(char *context, char *exten, int state, void *data) {
5139 +static int esel_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name) {
5140 struct esel_pvt *esel;
5143 ast_mutex_lock(&listlock);
5145 - esel_queue_extension_state(&esel->queue, context, exten, state, data);
5146 + esel_queue_extension_state(&esel->queue, context, exten, state, data, cid_num, cid_name);
5149 ast_mutex_unlock(&listlock);
5150 Add or convert channel operations so they can use the unique ID.
5152 --- a/include/asterisk/channel.h
5153 +++ b/include/asterisk/channel.h
5154 @@ -682,6 +682,18 @@ void ast_channel_free(struct ast_channe
5156 struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
5158 +/*! \brief Requests a channel
5159 + * \param type type of channel to request
5160 + * \param format requested channel format (codec)
5161 + * \param data data to pass to the channel requester
5162 + * \param status status
5163 + * \param uniqueid uniqueid
5164 + * Request a channel of a given type, with data as optional information used
5165 + * by the low level module. Sets the channels uniqueid to 'uniqueid'.
5166 + * \return Returns an ast_channel on success, NULL on failure.
5168 +struct ast_channel *ast_request_with_uniqueid(const char *type, int format, void *data, int *status, char *uniqueid);
5171 * \brief Request a channel of a given type, with data as optional information used
5172 * by the low level module and attempt to place a call on it
5173 @@ -697,8 +709,12 @@ struct ast_channel *ast_request(const ch
5175 struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname);
5177 +struct ast_channel *ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, char *uniqueid);
5179 struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname, struct outgoing_helper *oh);
5181 +struct ast_channel *__ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, struct outgoing_helper *oh, char *uniqueid);
5183 /*! \brief "Requests" a channel for sending a message
5184 * \param type type of channel to request
5185 * \param data data to pass to the channel requester
5186 @@ -990,6 +1006,8 @@ struct ast_channel *ast_get_channel_by_e
5187 /*! \brief Get next channel by exten (and optionally context) and lock it */
5188 struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
5189 const char *context);
5190 +/*! Get channel by uniqueid (locks channel) */
5191 +struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid);
5193 /*! ! \brief Waits for a digit
5194 * \param c channel to wait for a digit on
5195 --- a/main/channel.c
5196 +++ b/main/channel.c
5197 @@ -1017,7 +1017,7 @@ void ast_channel_undefer_dtmf(struct ast
5199 static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
5200 const char *name, const int namelen,
5201 - const char *context, const char *exten)
5202 + const char *context, const char *exten, const char *uniqueid)
5204 const char *msg = prev ? "deadlock" : "initial deadlock";
5206 @@ -1045,7 +1045,10 @@ static struct ast_channel *channel_find_
5207 * XXX Need a better explanation for this ...
5210 - if (name) { /* want match by name */
5212 + if (!strcasecmp(c->uniqueid, uniqueid))
5214 + } else if (name) { /* want match by name */
5215 if ((!namelen && strcasecmp(c->name, name)) ||
5216 (namelen && strncasecmp(c->name, name, namelen)))
5217 continue; /* name match failed */
5218 @@ -1100,39 +1103,44 @@ static struct ast_channel *channel_find_
5219 /*! \brief Browse channels in use */
5220 struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
5222 - return channel_find_locked(prev, NULL, 0, NULL, NULL);
5223 + return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
5226 /*! \brief Get channel by name and lock it */
5227 struct ast_channel *ast_get_channel_by_name_locked(const char *name)
5229 - return channel_find_locked(NULL, name, 0, NULL, NULL);
5230 + return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
5233 /*! \brief Get channel by name prefix and lock it */
5234 struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
5236 - return channel_find_locked(NULL, name, namelen, NULL, NULL);
5237 + return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
5240 /*! \brief Get next channel by name prefix and lock it */
5241 struct ast_channel *ast_walk_channel_by_name_prefix_locked(const struct ast_channel *chan, const char *name,
5244 - return channel_find_locked(chan, name, namelen, NULL, NULL);
5245 + return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
5248 /*! \brief Get channel by exten (and optionally context) and lock it */
5249 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
5251 - return channel_find_locked(NULL, NULL, 0, context, exten);
5252 + return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
5255 /*! \brief Get next channel by exten (and optionally context) and lock it */
5256 struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
5257 const char *context)
5259 - return channel_find_locked(chan, NULL, 0, context, exten);
5260 + return channel_find_locked(chan, NULL, 0, context, exten, NULL);
5263 +struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
5265 + return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
5268 /*! \brief Wait, look for hangups and condition arg */
5269 @@ -2862,6 +2870,12 @@ char *ast_channel_reason2str(int reason)
5271 struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
5273 + return __ast_request_and_dial_uniqueid(type, format, data,
5274 + timeout, outstate, 0, cid_num, cid_name, oh, NULL);
5277 +struct ast_channel *__ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cid_num, const char *cid_name, struct outgoing_helper *oh, char* uniqueid)
5281 struct ast_channel *chan;
5282 @@ -2873,7 +2887,7 @@ struct ast_channel *__ast_request_and_di
5284 outstate = &dummy_outstate; /* make outstate always a valid pointer */
5286 - chan = ast_request(type, format, data, &cause);
5287 + chan = ast_request_with_uniqueid(type, format, data, &cause, uniqueid);
5289 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
5290 /* compute error and return */
5291 @@ -2993,8 +3007,12 @@ struct ast_channel *ast_request_and_dial
5293 return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
5295 +struct ast_channel *ast_request_and_dial_uniqueid(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cidnum, const char *cidname, char *uniqueid)
5297 + return __ast_request_and_dial_uniqueid(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
5300 -struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
5301 +struct ast_channel *ast_request_with_uniqueid(const char *type, int format, void *data, int *cause, char *uniqueid)
5303 struct chanlist *chan;
5304 struct ast_channel *c;
5305 @@ -3033,6 +3051,7 @@ struct ast_channel *ast_request(const ch
5306 if (!(c = chan->tech->requester(type, capabilities | videoformat, data, cause)))
5309 + if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
5310 /* no need to generate a Newchannel event here; it is done in the channel_alloc call */
5313 @@ -3044,6 +3063,11 @@ struct ast_channel *ast_request(const ch
5317 +struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
5319 + return ast_request_with_uniqueid(type, format, data, cause, NULL);
5322 int ast_call(struct ast_channel *chan, char *addr, int timeout)
5324 /* Place an outgoing call, but don't wait any longer than timeout ms before returning.
5325 --- a/include/asterisk/pbx.h
5326 +++ b/include/asterisk/pbx.h
5327 @@ -717,9 +717,17 @@ int ast_async_goto_by_name(const char *c
5328 int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
5330 /*! Synchronously or asynchronously make an outbound call and send it to a
5331 + particular extension (extended version with callinpres and uniqueid) */
5332 +int ast_pbx_outgoing_exten_uniqueid(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
5334 +/*! Synchronously or asynchronously make an outbound call and send it to a
5335 particular application with given extension */
5336 int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
5338 +/*! Synchronously or asynchronously make an outbound call and send it to a
5339 + particular application with given extension (extended version with callinpres and uniqueid) */
5340 +int ast_pbx_outgoing_app_uniqueid(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
5343 * \brief Evaluate a condition
5347 @@ -4992,7 +4992,7 @@ static int ast_pbx_outgoing_cdr_failed(v
5348 return 0; /* success */
5351 -int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
5352 +int ast_pbx_outgoing_exten_uniqueid(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, char *uniqueid)
5354 struct ast_channel *chan;
5355 struct async_stat *as;
5356 @@ -5002,7 +5002,7 @@ int ast_pbx_outgoing_exten(const char *t
5360 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
5361 + chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
5365 @@ -5094,7 +5094,7 @@ int ast_pbx_outgoing_exten(const char *t
5367 goto outgoing_exten_cleanup;
5369 - chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
5370 + chan = ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
5374 @@ -5134,6 +5134,10 @@ outgoing_exten_cleanup:
5378 +int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
5380 + return ast_pbx_outgoing_exten_uniqueid(type, format, data, timeout, context, exten, priority, reason, sync, 0, cid_num, cid_name, vars, account, channel, NULL);
5385 @@ -5158,7 +5162,7 @@ static void *ast_pbx_run_app(void *data)
5389 -int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
5390 +int ast_pbx_outgoing_app_uniqueid(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid)
5392 struct ast_channel *chan;
5393 struct app_tmp *tmp;
5394 @@ -5177,7 +5181,7 @@ int ast_pbx_outgoing_app(const char *typ
5395 goto outgoing_app_cleanup;
5398 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
5399 + chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
5401 if (!chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
5402 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */
5403 @@ -5259,7 +5263,7 @@ int ast_pbx_outgoing_app(const char *typ
5405 goto outgoing_app_cleanup;
5407 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
5408 + chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
5412 @@ -5299,6 +5303,10 @@ outgoing_app_cleanup:
5416 +int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
5418 + return ast_pbx_outgoing_app_uniqueid(type, format, data, timeout, app, appdata, reason, sync, 0, cid_num, cid_name, vars, account, locked_channel, NULL);
5420 void __ast_context_destroy(struct ast_context *con, const char *registrar)
5422 struct ast_context *tmp, *tmpl=NULL;
5423 --- a/res/res_monitor.c
5424 +++ b/res/res_monitor.c
5425 @@ -340,6 +340,11 @@ int ast_monitor_stop(struct ast_channel
5426 result = ast_safe_system(tmp);
5428 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
5429 + manager_event(EVENT_FLAG_CALL, "MonitorStopped",
5431 + "Uniqueid: %s\r\n"
5433 + ,chan->name, chan->uniqueid, result);
5436 free(chan->monitor->format);
5437 @@ -518,18 +523,28 @@ static int start_monitor_action(struct m
5438 const char *fname = astman_get_header(m, "File");
5439 const char *format = astman_get_header(m, "Format");
5440 const char *mix = astman_get_header(m, "Mix");
5441 + const char *uniqueid = astman_get_header(m, "Uniqueid");
5442 const char *target_url = astman_get_header(m, "TargetURL");
5443 const char *target_script = astman_get_header(m, "TargetScript");
5446 - if (ast_strlen_zero(name)) {
5447 - astman_send_error(s, m, "No channel specified");
5448 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
5449 + astman_send_error(s, m, "No channel/uniqueid specified");
5453 + if (!ast_strlen_zero(uniqueid)) {
5454 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
5456 + astman_send_error(s, m, "No such uniqueid");
5459 - c = ast_get_channel_by_name_locked(name);
5463 + c = ast_get_channel_by_name_locked(name);
5465 astman_send_error(s, m, "No such channel");
5470 if (ast_strlen_zero(fname)) {
5471 @@ -570,16 +585,30 @@ static int stop_monitor_action(struct ma
5473 struct ast_channel *c = NULL;
5474 const char *name = astman_get_header(m, "Channel");
5475 + const char *uniqueid = astman_get_header(m, "Uniqueid");
5477 if (ast_strlen_zero(name)) {
5478 astman_send_error(s, m, "No channel specified");
5481 - c = ast_get_channel_by_name_locked(name);
5483 - astman_send_error(s, m, "No such channel");
5484 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
5485 + astman_send_error(s, m, "No channel/uniqueid specified");
5488 + if (!ast_strlen_zero(uniqueid)) {
5489 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
5491 + astman_send_error(s, m, "No such uniqueid");
5495 + c = ast_get_channel_by_name_locked(name);
5497 + astman_send_error(s, m, "No such channel");
5502 res = ast_monitor_stop(c, 1);
5503 ast_channel_unlock(c);
5505 --- a/apps/app_chanspy.c
5506 +++ b/apps/app_chanspy.c
5507 @@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
5509 static const char *tdesc = "Listen to a channel, and optionally whisper into it";
5510 static const char *app_chan = "ChanSpy";
5511 +static const char *app_chan_uniqueid = "ChanSpyChan";
5512 static const char *desc_chan =
5513 " ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
5514 "audio from an Asterisk channel. This includes the audio coming in and\n"
5515 @@ -87,6 +88,27 @@ static const char *desc_chan =
5519 +static const char *desc_uniqueid =
5520 +" ChanSpyChan(uniqueid[|options]): This application is used to listen to the\n"
5521 +"audio from an Asterisk channel. This includes the audio coming in and\n"
5522 +"out of the channel being spied on. The 'uniqueid' parameter has to be specified,\n"
5523 +" While spying, the following actions may be performed:\n"
5524 +" - Dialing # cycles the volume level.\n"
5526 +" q - Don't play a beep when beginning to spy on a channel, or speak the\n"
5527 +" selected channel name.\n"
5528 +" r[(basename)] - Record the session to the monitor spool directory. An\n"
5529 +" optional base for the filename may be specified. The\n"
5530 +" default is 'chanspy'.\n"
5531 +" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
5532 +" negative value refers to a quieter setting.\n"
5533 +" w - Enable 'whisper' mode, so the spying channel can talk to\n"
5534 +" the spied-on channel.\n"
5535 +" W - Enable 'private whisper' mode, so the spying channel can\n"
5536 +" talk to the spied-on channel but cannot listen to that\n"
5540 static const char *app_ext = "ExtenSpy";
5541 static const char *desc_ext =
5542 " ExtenSpy(exten[@context][|options]): This application is used to listen to the\n"
5543 @@ -456,7 +478,7 @@ static struct chanspy_ds *setup_chanspy_
5545 static struct chanspy_ds *next_channel(struct ast_channel *chan,
5546 const struct ast_channel *last, const char *spec,
5547 - const char *exten, const char *context, struct chanspy_ds *chanspy_ds)
5548 + const char *exten, const char *context, struct chanspy_ds *chanspy_ds, const char *uniqueid)
5550 struct ast_channel *this;
5552 @@ -465,6 +487,8 @@ redo:
5553 this = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
5555 this = ast_walk_channel_by_exten_locked(last, exten, context);
5556 + else if (uniqueid)
5557 + this = ast_get_channel_by_uniqueid_locked(uniqueid);
5559 this = ast_channel_walk_locked(last);
5561 @@ -485,7 +509,7 @@ redo:
5563 static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
5564 int volfactor, const int fd, const char *mygroup, const char *spec,
5565 - const char *exten, const char *context)
5566 + const char *exten, const char *context, const char *uniqueid)
5568 char nameprefix[AST_NAME_STRLEN];
5569 char peer_name[AST_NAME_STRLEN + 5];
5570 @@ -530,11 +554,11 @@ static int common_exec(struct ast_channe
5574 - for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds);
5575 + for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds, NULL);
5577 chanspy_ds_free(peer_chanspy_ds), prev = peer,
5578 peer_chanspy_ds = next_chanspy_ds ? next_chanspy_ds :
5579 - next_channel(chan, prev, spec, exten, context, &chanspy_ds), next_chanspy_ds = NULL) {
5580 + next_channel(chan, prev, spec, exten, context, &chanspy_ds, NULL), next_chanspy_ds = NULL) {
5582 int igrp = !mygroup;
5584 @@ -733,7 +757,7 @@ static int chanspy_exec(struct ast_chann
5588 - res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL);
5589 + res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL, NULL);
5593 @@ -818,7 +842,7 @@ static int extenspy_exec(struct ast_chan
5597 - res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context);
5598 + res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context, NULL);
5602 @@ -831,14 +855,100 @@ static int extenspy_exec(struct ast_chan
5606 +static int chanspychan_exec(struct ast_channel *chan, void *data)
5608 + struct ast_module_user *u;
5609 + char *options = NULL;
5610 + char *uniqueid = NULL;
5612 + char *mygroup = NULL;
5613 + char *recbase = NULL;
5615 + struct ast_flags flags;
5618 + int volfactor = 0;
5621 + data = ast_strdupa(data);
5623 + u = ast_module_user_add(chan);
5625 + if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
5626 + uniqueid = argv[0];
5628 + options = argv[1];
5630 + if (ast_strlen_zero(uniqueid)) {
5631 + ast_log(LOG_ERROR, "no uniqueid specified.\n");
5632 + ast_module_user_remove(u);
5638 + char *opts[OPT_ARG_ARRAY_SIZE];
5640 + ast_app_parse_options(spy_opts, &flags, opts, options);
5641 + if (ast_test_flag(&flags, OPTION_GROUP))
5642 + mygroup = opts[OPT_ARG_GROUP];
5644 + if (ast_test_flag(&flags, OPTION_RECORD) &&
5645 + !(recbase = opts[OPT_ARG_RECORD]))
5646 + recbase = "chanspy";
5648 + if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
5651 + if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
5652 + ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
5657 + if (ast_test_flag(&flags, OPTION_PRIVATE))
5658 + ast_set_flag(&flags, OPTION_WHISPER);
5661 + oldwf = chan->writeformat;
5662 + if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
5663 + ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
5664 + ast_module_user_remove(u);
5669 + char filename[512];
5671 + snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
5672 + if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) {
5673 + ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
5678 + res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, NULL, uniqueid);
5683 + if (oldwf && ast_set_write_format(chan, oldwf) < 0)
5684 + ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
5686 + ast_module_user_remove(u);
5692 static int unload_module(void)
5696 res |= ast_unregister_application(app_chan);
5697 + res |= ast_unregister_application(app_chan_uniqueid);
5698 res |= ast_unregister_application(app_ext);
5700 - ast_module_user_hangup_all();
5704 @@ -849,6 +959,7 @@ static int load_module(void)
5706 res |= ast_register_application(app_chan, chanspy_exec, tdesc, desc_chan);
5707 res |= ast_register_application(app_ext, extenspy_exec, tdesc, desc_ext);
5708 + res |= ast_register_application(app_chan_uniqueid, chanspychan_exec, tdesc, desc_uniqueid);
5712 --- a/main/manager.c
5713 +++ b/main/manager.c
5714 @@ -87,6 +87,8 @@ struct fast_originate_helper {
5715 char idtext[AST_MAX_EXTENSION];
5716 char account[AST_MAX_ACCOUNT_CODE];
5719 + char uniqueid[64];
5720 struct ast_variable *vars;
5723 @@ -1416,11 +1418,20 @@ static int action_hangup(struct mansessi
5725 struct ast_channel *c = NULL;
5726 const char *name = astman_get_header(m, "Channel");
5727 - if (ast_strlen_zero(name)) {
5728 - astman_send_error(s, m, "No channel specified");
5729 + const char *uniqueid = astman_get_header(m, "Uniqueid");
5731 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
5732 + astman_send_error(s, m, "No channel or uniqueid specified");
5735 - c = ast_get_channel_by_name_locked(name);
5737 + if (!ast_strlen_zero(uniqueid)) {
5738 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
5740 + if (!ast_strlen_zero(name))
5741 + c = ast_get_channel_by_name_locked(name);
5745 astman_send_error(s, m, "No such channel");
5747 @@ -1671,12 +1682,18 @@ static int action_redirect(struct manses
5748 const char *exten = astman_get_header(m, "Exten");
5749 const char *context = astman_get_header(m, "Context");
5750 const char *priority = astman_get_header(m, "Priority");
5751 + const char *uniqueid = astman_get_header(m, "Uniqueid");
5752 + const char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
5753 + const char *exten2 = astman_get_header(m, "ExtraExten");
5754 + const char *context2 = astman_get_header(m, "ExtraContext");
5755 + const char *priority2 = astman_get_header(m, "ExtraPriority");
5756 struct ast_channel *chan, *chan2 = NULL;
5761 - if (ast_strlen_zero(name)) {
5762 - astman_send_error(s, m, "Channel not specified");
5763 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
5764 + astman_send_error(s, m, "Channel or Uniqueid not specified");
5767 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
5768 @@ -1685,8 +1702,18 @@ static int action_redirect(struct manses
5772 + if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%d", &pi2) != 1)) {
5773 + if ((pi = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) {
5774 + astman_send_error(s, m, "Invalid extra priority\n");
5778 /* XXX watch out, possible deadlock!!! */
5779 - chan = ast_get_channel_by_name_locked(name);
5780 + if (!ast_strlen_zero(uniqueid)) {
5781 + chan = ast_get_channel_by_uniqueid_locked(uniqueid);
5783 + chan = ast_get_channel_by_name_locked(name);
5787 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
5788 @@ -1698,8 +1725,11 @@ static int action_redirect(struct manses
5789 ast_channel_unlock(chan);
5792 - if (!ast_strlen_zero(name2))
5793 + if (!ast_strlen_zero(uniqueid2)) {
5794 + chan2 = ast_get_channel_by_uniqueid_locked(uniqueid2);
5795 + } else if (!ast_strlen_zero(name2)) {
5796 chan2 = ast_get_channel_by_name_locked(name2);
5798 if (chan2 && ast_check_hangup(chan2)) {
5799 astman_send_error(s, m, "Redirect failed, extra channel not up.\n");
5800 ast_channel_unlock(chan);
5801 @@ -1708,9 +1738,9 @@ static int action_redirect(struct manses
5803 res = ast_async_goto(chan, context, exten, pi);
5805 - if (!ast_strlen_zero(name2)) {
5806 + if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
5808 - res = ast_async_goto(chan2, context, exten, pi);
5809 + res = ast_async_goto(chan2, context2, exten2, pi2);
5813 @@ -1789,15 +1819,15 @@ static void *fast_originate(void *data)
5814 char requested_channel[AST_CHANNEL_NAME];
5816 if (!ast_strlen_zero(in->app)) {
5817 - res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1,
5818 + res = ast_pbx_outgoing_app_uniqueid(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres,
5819 S_OR(in->cid_num, NULL),
5820 S_OR(in->cid_name, NULL),
5821 - in->vars, in->account, &chan);
5822 + in->vars, in->account, &chan, in->uniqueid);
5824 - res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
5825 + res = ast_pbx_outgoing_exten_uniqueid(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres,
5826 S_OR(in->cid_num, NULL),
5827 S_OR(in->cid_name, NULL),
5828 - in->vars, in->account, &chan);
5829 + in->vars, in->account, &chan, in->uniqueid);
5833 @@ -1857,6 +1887,7 @@ static int action_originate(struct manse
5834 const char *appdata = astman_get_header(m, "Data");
5835 const char *async = astman_get_header(m, "Async");
5836 const char *id = astman_get_header(m, "ActionID");
5837 + const char *callingpres = astman_get_header(m, "CallingPres");
5838 struct ast_variable *vars = astman_get_variables(m);
5840 char *l = NULL, *n = NULL;
5841 @@ -1866,6 +1897,9 @@ static int action_originate(struct manse
5847 + char idText[256] = "";
5850 pthread_attr_t attr;
5851 @@ -1883,6 +1917,10 @@ static int action_originate(struct manse
5852 astman_send_error(s, m, "Invalid timeout\n");
5855 + if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
5856 + astman_send_error(s, m, "Invalid CallingPres\n");
5859 ast_copy_string(tmp, name, sizeof(tmp));
5861 data = strchr(tmp, '/');
5862 @@ -1902,6 +1940,7 @@ static int action_originate(struct manse
5863 if (ast_strlen_zero(l))
5866 + uniqueid = ast_alloc_uniqueid();
5867 if (ast_true(async)) {
5868 struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
5870 @@ -1921,8 +1960,10 @@ static int action_originate(struct manse
5871 ast_copy_string(fast->context, context, sizeof(fast->context));
5872 ast_copy_string(fast->exten, exten, sizeof(fast->exten));
5873 ast_copy_string(fast->account, account, sizeof(fast->account));
5874 + ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
5876 fast->priority = pi;
5877 + fast->callingpres = cpresi;
5878 pthread_attr_init(&attr);
5879 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
5880 if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
5881 @@ -1933,19 +1974,28 @@ static int action_originate(struct manse
5882 pthread_attr_destroy(&attr);
5884 } else if (!ast_strlen_zero(app)) {
5885 - res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
5886 + res = ast_pbx_outgoing_app_uniqueid(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
5888 if (exten && context && pi)
5889 - res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
5890 + res = ast_pbx_outgoing_exten_uniqueid(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
5892 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
5897 - astman_send_ack(s, m, "Originate successfully queued");
5900 + if (id && !ast_strlen_zero(id)) {
5901 + snprintf(idText,256,"ActionID: %s\r\n",id);
5903 + ast_cli(s->fd, "Response: Success\r\n"
5905 + "Message: Originate successfully queued\r\n"
5906 + "Uniqueid: %s\r\n"
5908 + idText, uniqueid);
5910 astman_send_error(s, m, "Originate failed");
5915 --- a/include/asterisk/channel.h
5916 +++ b/include/asterisk/channel.h
5919 #include "asterisk/abstract_jb.h"
5921 +/* Max length of the uniqueid */
5922 +#define AST_MAX_UNIQUEID 64
5926 #include "asterisk/poll-compat.h"
5927 @@ -1039,6 +1042,8 @@ int ast_waitfordigit_full(struct ast_cha
5928 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
5929 int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd);
5931 +char *ast_alloc_uniqueid(void);
5933 /*! \brief Report DTMF on channel 0 */
5934 #define AST_BRIDGE_DTMF_CHANNEL_0 (1 << 0)
5935 /*! \brief Report DTMF on channel 1 */
5936 --- a/main/channel.c
5937 +++ b/main/channel.c
5938 @@ -706,6 +706,15 @@ static const struct ast_channel_tech nul
5939 .description = "Null channel (should not see this)",
5942 +/*! \brief Create a uniqueid */
5943 +char *ast_alloc_uniqueid(void) {
5945 + uniqueid = malloc(64);
5946 + if (!uniqueid) return NULL;
5947 + snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYSTEM_NAME, ast_mainpid, (long)time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
5951 /*! \brief Create a new channel structure */
5952 struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt, ...)
5954 --- a/include/asterisk/features.h
5955 +++ b/include/asterisk/features.h
5956 @@ -47,6 +47,8 @@ struct ast_call_feature {
5960 +extern int ast_autoanswer_login(struct ast_channel *chan, void *data);
5961 +extern int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data);
5963 /*! \brief Park a call and read back parked location
5964 * \param chan the channel to actually be parked
5965 --- a/res/res_features.c
5966 +++ b/res/res_features.c
5968 * the project provides a web site, mailing lists and IRC
5969 * channels for your use.
5971 + * Copyright (C) 2004, Junghanns.NET GmbH
5973 + * Klaus-Peter Junghanns <kpj@junghanns.net>
5975 * This program is free software, distributed under the terms of
5976 * the GNU General Public License Version 2. See the LICENSE file
5977 * at the top of the source tree.
5978 @@ -132,6 +136,20 @@ static char *descrip2 = "Park():"
5979 "it already exists. In that case, execution will continue at next\n"
5982 +static char *autoanswerlogin = "AutoanswerLogin";
5984 +static char *synopsis3 = "Log in for autoanswer";
5986 +static char *descrip3 = "AutoanswerLogin([context]|exten):"
5987 +"Used to login to the autoanswer application for an extension.\n";
5989 +static char *autoanswer = "Autoanswer";
5991 +static char *synopsis4 = "Autoanswer a call";
5993 +static char *descrip4 = "Autoanswer([context]|exten):"
5994 +"Used to autoanswer a call for an extension.\n";
5996 static struct ast_app *monitor_app = NULL;
5997 static int monitor_ok = 1;
5999 @@ -150,6 +168,23 @@ struct parkeduser {
6000 struct parkeduser *next;
6003 +/* auto answer user */
6005 + struct ast_channel *chan;
6006 + struct timeval start;
6007 + /* waiting on this extension/context */
6008 + char exten[AST_MAX_EXTENSION];
6009 + char context[AST_MAX_EXTENSION];
6012 + struct aauser *next;
6016 +static struct aauser *aalot;
6017 +AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
6018 +static pthread_t autoanswer_thread;
6020 static struct parkeduser *parkinglot;
6022 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
6023 @@ -405,11 +440,13 @@ static int park_call_full(struct ast_cha
6027 - "CallerIDName: %s\r\n",
6028 + "CallerIDName: %s\r\n"
6029 + "Uniqueid: %s\r\n",
6030 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
6031 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
6032 S_OR(pu->chan->cid.cid_num, "<unknown>"),
6033 - S_OR(pu->chan->cid.cid_name, "<unknown>")
6034 + S_OR(pu->chan->cid.cid_name, "<unknown>"),
6035 + pu->chan->uniqueid
6038 if (peer && adsipark && ast_adsi_available(peer)) {
6039 @@ -1656,11 +1693,13 @@ static void post_manager_event(const cha
6043 - "CallerIDName: %s\r\n\r\n",
6044 + "CallerIDName: %s\r\n"
6045 + "Uniqueid: %s\r\n\r\n",
6048 S_OR(chan->cid.cid_num, "<unknown>"),
6049 - S_OR(chan->cid.cid_name, "<unknown>")
6050 + S_OR(chan->cid.cid_name, "<unknown>"),
6055 @@ -1928,10 +1967,12 @@ static int park_exec(struct ast_channel
6059 - "CallerIDName: %s\r\n",
6060 + "CallerIDName: %s\r\n"
6061 + "Uniqueid: %s\r\n",
6062 pu->parkingexten, pu->chan->name, chan->name,
6063 S_OR(pu->chan->cid.cid_num, "<unknown>"),
6064 - S_OR(pu->chan->cid.cid_name, "<unknown>")
6065 + S_OR(pu->chan->cid.cid_name, "<unknown>"),
6066 + pu->chan->uniqueid
6070 @@ -2085,15 +2126,10 @@ static struct ast_cli_entry cli_show_fea
6071 handle_showfeatures, NULL,
6074 -static struct ast_cli_entry cli_features[] = {
6075 - { { "feature", "show", NULL },
6076 - handle_showfeatures, "Lists configured features",
6077 - showfeatures_help, NULL, &cli_show_features_deprecated },
6078 +static char showautoanswer_help[] =
6079 +"Usage: show autoanswer\n"
6080 +" Lists currently logged in autoanswer users.\n";
6082 - { { "show", "parkedcalls", NULL },
6083 - handle_parkedcalls, "Lists parked calls",
6084 - showparked_help },
6087 /*! \brief Dump lot status */
6088 static int manager_parking_status( struct mansession *s, const struct message *m)
6089 @@ -2117,12 +2153,13 @@ static int manager_parking_status( struc
6092 "CallerIDName: %s\r\n"
6093 + "Uniqueid: %s\r\n\r\n"
6096 cur->parkingnum, cur->chan->name, cur->peername,
6097 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
6098 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
6099 - S_OR(cur->chan->cid.cid_name, ""),
6100 + S_OR(cur->chan->cid.cid_name, ""), cur->chan->uniqueid,
6104 @@ -2197,6 +2234,427 @@ static int manager_park(struct mansessio
6108 +static int handle_autoanswer(int fd, int argc, char *argv[])
6110 + struct aauser *cur;
6112 + ast_cli(fd, "%25s %10s %15s \n", "Channel"
6113 + , "Extension", "Context");
6115 + ast_mutex_lock(&autoanswer_lock);
6119 + ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
6124 + ast_mutex_unlock(&autoanswer_lock);
6126 + return RESULT_SUCCESS;
6129 +static struct ast_cli_entry cli_features[] = {
6130 + { { "feature", "list", NULL },
6131 + handle_showfeatures, "Lists configured features",
6132 + showfeatures_help, NULL, &cli_show_features_deprecated },
6134 + { { "show", "parkedcalls", NULL },
6135 + handle_parkedcalls, "Lists parked calls",
6136 + showparked_help },
6138 + { { "show", "autoanswer", NULL },
6139 + handle_autoanswer, "Lists autoanswer users",
6140 + showautoanswer_help },
6142 +int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
6144 + struct ast_channel *chan;
6145 + struct ast_frame *f;
6146 + /* Make a new, fake channel that we'll use to masquerade in the real one */
6147 + chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name);
6149 + /* Let us keep track of the channel name */
6150 + ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name);
6151 + /* Make formats okay */
6152 + chan->readformat = rchan->readformat;
6153 + chan->writeformat = rchan->writeformat;
6154 + ast_channel_masquerade(chan, rchan);
6155 + /* Setup the extensions and such */
6156 + strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
6157 + strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
6158 + chan->priority = rchan->priority;
6159 + /* might be dirty but we want trackable channels */
6160 + ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
6161 + /* Make the masq execute */
6162 + f = ast_read(chan);
6165 + ast_autoanswer_login(chan, data);
6167 + ast_log(LOG_WARNING, "Unable to create aa channel\n");
6173 +static int autoanswer_login_exec(struct ast_channel *chan, void *data)
6176 + struct ast_module_user *u;
6178 + u = ast_module_user_add(chan);
6180 + ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
6183 + res = ast_masq_autoanswer_login(chan, data);
6184 + ast_module_user_remove(u);
6188 +int ast_autoanswer_login(struct ast_channel *chan, void *data)
6190 + /* We put the user in the parking list, then wake up the parking thread to be sure it looks
6191 + after these channels too */
6192 + struct ast_context *con;
6193 + char exten[AST_MAX_EXTENSION];
6194 + struct aauser *pu,*pl = NULL;
6195 + char *s, *stringp, *aacontext, *aaexten = NULL;
6197 + s = ast_strdupa((void *) data);
6199 + aacontext = strsep(&stringp, "|");
6200 + aaexten = strsep(&stringp, "|");
6202 + aaexten = aacontext;
6206 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
6210 + aacontext = "default";
6214 + ast_mutex_lock(&autoanswer_lock);
6217 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
6219 + pl->next = pu->next;
6227 + ast_mutex_unlock(&autoanswer_lock);
6229 + ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
6230 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
6232 + "Uniqueid: %s\r\n"
6235 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
6236 + ast_hangup(pu->chan);
6239 + pu = malloc(sizeof(struct aauser));
6241 + memset(pu, 0, sizeof(pu));
6242 + ast_mutex_lock(&autoanswer_lock);
6243 + chan->appl = "Autoanswer";
6244 + chan->data = NULL;
6247 + if (chan->_state != AST_STATE_UP) {
6251 + /* Start music on hold */
6252 + ast_moh_start(pu->chan, NULL, NULL);
6253 + gettimeofday(&pu->start, NULL);
6254 + strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
6255 + strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
6258 + con = ast_context_find(aacontext);
6260 + con = ast_context_create(NULL,aacontext, registrar);
6262 + ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
6266 + snprintf(exten, sizeof(exten), "%s", aaexten);
6267 + ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
6270 + ast_mutex_unlock(&autoanswer_lock);
6271 + /* Wake up the (presumably select()ing) thread */
6272 + pthread_kill(autoanswer_thread, SIGURG);
6273 + if (option_verbose > 1)
6274 + ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
6275 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
6277 + "Uniqueid: %s\r\n"
6280 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
6284 + ast_log(LOG_WARNING, "Out of memory\n");
6290 +static void autoanswer_reregister_extensions(void)
6292 + struct aauser *cur;
6293 + struct ast_context *con;
6294 + char exten[AST_MAX_EXTENSION];
6295 + char args[AST_MAX_EXTENSION];
6297 + ast_mutex_lock(&autoanswer_lock);
6301 + con = ast_context_find(cur->context);
6303 + con = ast_context_create(NULL,cur->context, registrar);
6305 + ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", cur->context);
6309 + snprintf(exten, sizeof(exten), "%s", cur->exten);
6310 + snprintf(args, sizeof(args), "%s|%s", cur->context, cur->exten);
6311 + ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)args), free, registrar);
6316 + ast_mutex_unlock(&autoanswer_lock);
6318 +static void *do_autoanswer_thread(void *ignore)
6321 + struct ast_context *con;
6322 + char exten[AST_MAX_EXTENSION];
6323 + struct aauser *pu, *pl, *pt = NULL;
6324 + struct timeval tv;
6325 + struct ast_frame *f;
6327 + fd_set rfds, efds;
6328 + fd_set nrfds, nefds;
6334 + ast_mutex_lock(&autoanswer_lock);
6337 + gettimeofday(&tv, NULL);
6341 + tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
6342 + for (x=0;x<AST_MAX_FDS;x++) {
6343 + if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
6344 + if (FD_ISSET(pu->chan->fds[x], &efds))
6345 + ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
6347 + ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
6348 + pu->chan->fdno = x;
6349 + /* See if they need servicing */
6350 + f = ast_read(pu->chan);
6351 + if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
6352 + /* There's a problem, hang them up*/
6353 + if (option_verbose > 1)
6354 + ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
6355 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
6357 + "Uniqueid: %s\r\n"
6360 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
6361 + ast_hangup(pu->chan);
6362 + con = ast_context_find(pu->context);
6364 + snprintf(exten, sizeof(exten), "%s", pu->exten);
6365 + if (ast_context_remove_extension2(con, exten, 1, registrar))
6366 + ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
6368 + ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
6370 + /* And take them out of the parking lot */
6372 + pl->next = pu->next;
6380 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
6382 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
6386 + if (x >= AST_MAX_FDS) {
6387 +std: for (x=0;x<AST_MAX_FDS;x++) {
6388 + /* Keep this one for next one */
6389 + if (pu->chan->fds[x] > -1) {
6390 + FD_SET(pu->chan->fds[x], &nrfds);
6391 + FD_SET(pu->chan->fds[x], &nefds);
6392 + if (pu->chan->fds[x] > max)
6393 + max = pu->chan->fds[x];
6396 + /* Keep track of our longest wait */
6397 + if ((tms < ms) || (ms < 0))
6403 + ast_mutex_unlock(&autoanswer_lock);
6406 + tv.tv_sec = ms / 1000;
6407 + tv.tv_usec = (ms % 1000) * 1000;
6408 + /* Wait for something to happen */
6409 + ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
6410 + pthread_testcancel();
6412 + return NULL; /* Never reached */
6415 +static int autoanswer_exec(struct ast_channel *chan, void *data)
6418 + struct ast_channel *peer=NULL;
6419 + struct aauser *pu, *pl=NULL;
6420 + struct ast_bridge_config config;
6421 + char *s, *stringp, *aacontext, *aaexten = NULL;
6422 + char datastring[80];
6423 + struct ast_module_user *u;
6427 + ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
6430 + s = ast_strdupa((void *) data);
6432 + aacontext = strsep(&stringp, "|");
6433 + aaexten = strsep(&stringp, "|");
6435 + aaexten = aacontext;
6439 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
6443 + aacontext = "default";
6447 + u = ast_module_user_add(chan);
6448 + ast_mutex_lock(&autoanswer_lock);
6451 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
6453 + pl->next = pu->next;
6461 + ast_mutex_unlock(&autoanswer_lock);
6467 + /* JK02: it helps to answer the channel if not already up */
6468 + if (chan->_state != AST_STATE_UP) {
6473 + ast_moh_stop(peer);
6474 + /* Play a courtesy beep in the callED channel to prefix the bridge connecting */
6475 + if (!ast_strlen_zero(courtesytone)) {
6476 + if (!ast_streamfile(peer, courtesytone, peer->language)) {
6477 + if (ast_waitstream(peer, "") < 0) {
6478 + ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
6485 + res = ast_channel_make_compatible(chan, peer);
6487 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
6491 + /* This runs sorta backwards, since we give the incoming channel control, as if it
6492 + were the person called. */
6493 + if (option_verbose > 2)
6494 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered %s\n", peer->name, chan->name);
6495 + manager_event(EVENT_FLAG_CALL, "Autoanswer",
6497 + "Uniqueid: %s\r\n"
6498 + "Channel2: %s\r\n"
6499 + "Uniqueid2: %s\r\n"
6502 + ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
6505 + memset(&config,0,sizeof(struct ast_bridge_config));
6506 + ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
6507 + ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
6508 + config.timelimit = 0;
6509 + config.play_warning = 0;
6510 + config.warning_freq = 0;
6511 + config.warning_sound=NULL;
6512 + res = ast_bridge_call(chan,peer,&config);
6514 + if (option_verbose > 2)
6515 + ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
6517 + snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
6518 + ast_autoanswer_login(peer, datastring);
6521 + if (option_verbose > 2)
6522 + ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
6525 + ast_module_user_remove(u);
6530 int ast_pickup_call(struct ast_channel *chan)
6532 @@ -2460,6 +2918,7 @@ static int load_config(void)
6534 static int reload(void)
6536 + autoanswer_reregister_extensions();
6537 return load_config();
6540 @@ -2483,6 +2942,12 @@ static int load_module(void)
6541 "Park a channel", mandescr_park);
6544 + ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
6546 + res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
6548 + res |= ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
6550 res |= ast_devstate_prov_add("Park", metermaidstate);
6553 @@ -2497,6 +2962,8 @@ static int unload_module(void)
6554 ast_manager_unregister("Park");
6555 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
6556 ast_unregister_application(parkcall);
6557 + ast_unregister_application(autoanswer);
6558 + ast_unregister_application(autoanswerlogin);
6559 ast_devstate_prov_del("Park");
6560 return ast_unregister_application(parkedcall);
6562 --- a/include/asterisk/features.h
6563 +++ b/include/asterisk/features.h
6564 @@ -72,6 +72,12 @@ int ast_park_call(struct ast_channel *ch
6566 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
6568 +extern int ast_hold_call(struct ast_channel *chan, struct ast_channel *host);
6569 +extern int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *host);
6570 +extern int ast_retrieve_call(struct ast_channel *chan, char *uniqueid);
6571 +extern int ast_retrieve_call_to_death(char *uniqueid);
6572 +extern struct ast_channel *ast_get_holded_call(char *uniqueid);
6574 /*! \brief Determine system parking extension
6575 * Returns the call parking extension for drivers that provide special
6576 call parking help */
6577 --- a/res/res_features.c
6578 +++ b/res/res_features.c
6579 @@ -66,6 +66,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
6580 #include "asterisk/adsi.h"
6581 #include "asterisk/devicestate.h"
6582 #include "asterisk/monitor.h"
6583 +#include "asterisk/indications.h"
6585 #define DEFAULT_PARK_TIME 45000
6586 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
6587 @@ -84,6 +85,7 @@ enum {
6590 static char *parkedcall = "ParkedCall";
6591 +static char *holdedcall = "HoldedCall";
6593 static int parkaddhints = 0; /*!< Add parking hints automatically */
6594 static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
6595 @@ -168,6 +170,22 @@ struct parkeduser {
6596 struct parkeduser *next;
6599 +struct holdeduser {
6600 + struct ast_channel *chan;
6601 + struct timeval start;
6605 + /* Where to go if our parking time expires */
6606 + char context[AST_MAX_EXTENSION];
6607 + char exten[AST_MAX_EXTENSION];
6610 + char uniqueid[AST_MAX_UNIQUEID];
6611 + char uniqueidpeer[AST_MAX_UNIQUEID];
6612 + struct holdeduser *next;
6615 /* auto answer user */
6617 struct ast_channel *chan;
6618 @@ -187,10 +205,16 @@ static pthread_t autoanswer_thread;
6620 static struct parkeduser *parkinglot;
6622 +static struct holdeduser *holdlist;
6624 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
6626 +AST_MUTEX_DEFINE_STATIC(holding_lock);
6628 static pthread_t parking_thread;
6630 +static pthread_t holding_thread;
6632 char *ast_parking_ext(void)
6635 @@ -2052,6 +2076,282 @@ static int park_exec(struct ast_channel
6639 +int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
6641 + /* We put the user in the parking list, then wake up the parking thread to be sure it looks
6642 + after these channels too */
6643 + struct holdeduser *pu;
6644 + pu = malloc(sizeof(struct holdeduser));
6646 + memset(pu, 0, sizeof(pu));
6647 + ast_mutex_lock(&holding_lock);
6648 + chan->appl = "Holded Call";
6649 + chan->data = NULL;
6652 + strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
6653 + strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
6654 + /* Start music on hold */
6655 + ast_moh_start(pu->chan, NULL, NULL);
6656 + gettimeofday(&pu->start, NULL);
6657 + pu->next = holdlist;
6659 + ast_mutex_unlock(&holding_lock);
6660 + /* Wake up the (presumably select()ing) thread */
6661 + pthread_kill(holding_thread, SIGURG);
6663 + manager_event(EVENT_FLAG_CALL, "HoldedCall",
6664 + "Channel1: %s\r\n"
6665 + "Channel2: %s\r\n"
6666 + "Uniqueid1: %s\r\n"
6667 + "Uniqueid2: %s\r\n"
6668 + ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
6671 + ast_log(LOG_WARNING, "Out of memory\n");
6677 +int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
6679 + struct ast_channel *chan;
6680 + struct ast_frame *f;
6681 + /* Make a new, fake channel that we'll use to masquerade in the real one */
6682 + chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name);
6684 + /* Let us keep track of the channel name */
6685 + ast_string_field_build(chan, name, "Onhold/%s",rchan->name);
6686 + /* Make formats okay */
6687 + chan->readformat = rchan->readformat;
6688 + chan->writeformat = rchan->writeformat;
6689 + ast_channel_masquerade(chan, rchan);
6690 + /* Setup the extensions and such */
6691 + strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
6692 + strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
6693 + chan->priority = rchan->priority;
6694 + /* this might be dirty, but we need to preserve the uniqueid */
6695 + ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
6696 + /* Make the masq execute */
6697 + f = ast_read(chan);
6700 + ast_hold_call(chan, peer);
6703 + ast_log(LOG_WARNING, "Unable to create holded channel\n");
6709 +int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
6711 + int res=-1, dres=-1;
6712 + struct ast_channel *peer=NULL;
6713 + struct ast_bridge_config config;
6715 + peer = ast_get_holded_call(uniqueid);
6717 + /* JK02: it helps to answer the channel if not already up */
6718 + if (chan->_state != AST_STATE_UP) {
6723 + ast_mutex_unlock(&peer->lock);
6724 + ast_moh_stop(peer);
6725 + res = ast_channel_make_compatible(chan, peer);
6727 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
6731 + /* This runs sorta backwards, since we give the incoming channel control, as if it
6732 + were the person called. */
6733 + if (option_verbose > 2)
6734 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
6736 + memset(&config,0,sizeof(struct ast_bridge_config));
6737 + ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
6738 + ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
6739 + config.timelimit = 0;
6740 + config.play_warning = 0;
6741 + config.warning_freq = 0;
6742 + config.warning_sound=NULL;
6743 + res = ast_bridge_call(chan,peer,&config);
6745 + /* Simulate the PBX hanging up */
6746 + if (res != AST_PBX_NO_HANGUP_PEER)
6750 + /* XXX Play a message XXX */
6751 + dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
6753 + dres = ast_waitstream(chan, "");
6755 + ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
6762 +int ast_retrieve_call_to_death(char *uniqueid)
6765 + struct ast_channel *peer=NULL;
6767 + peer = ast_get_holded_call(uniqueid);
6771 + if (option_verbose > 2)
6772 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
6773 + ast_mutex_unlock(&peer->lock);
6776 + ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
6781 +struct ast_channel *ast_get_holded_call(char *uniqueid)
6784 + struct ast_channel *peer=NULL;
6785 + struct holdeduser *pu, *pl=NULL;
6787 + ast_mutex_lock(&holding_lock);
6790 + if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
6792 + pl->next = pu->next;
6794 + holdlist = pu->next;
6800 + ast_mutex_unlock(&holding_lock);
6802 + peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
6806 + if (option_verbose > 2)
6807 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
6808 + ast_moh_stop(peer);
6811 + if (option_verbose > 2)
6812 + ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
6816 + ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
6821 +/* this is our autmagically service thread that keeps channels onhold happy */
6822 +static void *do_holding_thread(void *ignore)
6825 + struct holdeduser *pu, *pl, *pt = NULL;
6826 + struct timeval tv;
6827 + struct ast_frame *f;
6829 + fd_set rfds, efds;
6830 + fd_set nrfds, nefds;
6836 + ast_mutex_lock(&holding_lock);
6839 + gettimeofday(&tv, NULL);
6843 + tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
6844 + for (x=0;x<AST_MAX_FDS;x++) {
6845 + if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
6846 + if (FD_ISSET(pu->chan->fds[x], &efds))
6847 + ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
6849 + ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
6850 + pu->chan->fdno = x;
6851 + /* See if they need servicing */
6852 + f = ast_read(pu->chan);
6853 + if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
6854 + /* There's a problem, hang them up*/
6855 + if (option_verbose > 1)
6856 + ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
6857 + ast_hangup(pu->chan);
6858 + /* find the corresponding channel and hang them up too! */
6859 + /* but only if it is not bridged yet! */
6860 + /* And take them out of the parking lot */
6862 + pl->next = pu->next;
6864 + holdlist = pu->next;
6870 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
6872 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
6876 + if (x >= AST_MAX_FDS) {
6877 +std: for (x=0;x<AST_MAX_FDS;x++) {
6878 + /* Keep this one for next one */
6879 + if (pu->chan->fds[x] > -1) {
6880 + FD_SET(pu->chan->fds[x], &nrfds);
6881 + FD_SET(pu->chan->fds[x], &nefds);
6882 + if (pu->chan->fds[x] > max)
6883 + max = pu->chan->fds[x];
6886 + /* Keep track of our longest wait */
6887 + if ((tms < ms) || (ms < 0))
6893 + ast_mutex_unlock(&holding_lock);
6896 + tv.tv_sec = ms / 1000;
6897 + tv.tv_usec = (ms % 1000) * 1000;
6898 + /* Wait for something to happen */
6899 + ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
6900 + pthread_testcancel();
6902 + return NULL; /* Never reached */
6905 +static int retrieve_call_exec(struct ast_channel *chan, void *data) {
6907 + struct ast_module_user *u;
6908 + char *uniqueid = (char *)data;
6909 + u = ast_module_user_add(chan);
6910 + res = ast_retrieve_call(chan, uniqueid);
6911 + ast_module_user_remove(u);
6915 static int handle_showfeatures(int fd, int argc, char *argv[])
6918 @@ -2933,6 +3233,7 @@ static int load_module(void)
6920 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
6921 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
6922 + ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
6923 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
6925 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
6926 @@ -2942,6 +3243,7 @@ static int load_module(void)
6927 "Park a channel", mandescr_park);
6930 + res |= ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
6931 ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
6933 res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
6934 @@ -2964,6 +3266,7 @@ static int unload_module(void)
6935 ast_unregister_application(parkcall);
6936 ast_unregister_application(autoanswer);
6937 ast_unregister_application(autoanswerlogin);
6938 + ast_unregister_application(holdedcall);
6939 ast_devstate_prov_del("Park");
6940 return ast_unregister_application(parkedcall);
6942 --- a/channels/chan_zap.c
6943 +++ b/channels/chan_zap.c
6944 @@ -77,6 +77,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi
6946 #include <bristuffed/libpri.h>
6949 +#include <libgsmat.h>
6952 #include "asterisk/lock.h"
6953 #include "asterisk/channel.h"
6954 @@ -185,6 +188,7 @@ static const char config[] = "zapata.con
6955 #define SIG_FXOGS ZT_SIG_FXOGS
6956 #define SIG_FXOKS ZT_SIG_FXOKS
6957 #define SIG_PRI ZT_SIG_CLEAR
6958 +#define SIG_GSM (0x100000 | ZT_SIG_CLEAR)
6959 #define SIG_SF ZT_SIG_SF
6960 #define SIG_SFWINK (0x0100000 | ZT_SIG_SF)
6961 #define SIG_SF_FEATD (0x0200000 | ZT_SIG_SF)
6962 @@ -234,6 +238,8 @@ static int matchdigittimeout = 3000;
6963 /*! \brief Protect the interface list (of zt_pvt's) */
6964 AST_MUTEX_DEFINE_STATIC(iflock);
6966 +static char gsm_modem_pin[20];
6967 +static char gsm_modem_exten[AST_MAX_EXTENSION];
6969 static int ifcount = 0;
6971 @@ -251,6 +257,7 @@ static enum ast_bridge_result zt_bridge(
6973 static int zt_sendtext(struct ast_channel *c, const char *text);
6975 +static int zt_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu);
6977 /*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
6978 static inline int zt_get_event(int fd)
6979 @@ -364,6 +371,19 @@ struct zt_pri {
6986 + ast_mutex_t lock; /* Mutex */
6989 + struct gsm_modul *modul;
6992 + char exten[AST_MAX_EXTENSION]; /* Where to idle extra calls */
6993 + struct zt_pvt *pvt;
6997 static struct zt_pri pris[NUM_SPANS];
6999 @@ -392,6 +412,7 @@ struct zt_pri;
7000 #define POLARITY_REV 1
7004 static struct zt_distRings drings;
7006 struct distRingData {
7007 @@ -604,6 +625,9 @@ static struct zt_pvt {
7012 + struct zt_gsm gsm;
7017 @@ -710,7 +734,7 @@ static struct zt_chan_conf zt_chan_conf_
7018 static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause);
7019 static int zt_digit_begin(struct ast_channel *ast, char digit);
7020 static int zt_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
7021 -static int zt_sendtext(struct ast_channel *c, const char *text);
7022 +static int zt_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu);
7023 static int zt_call(struct ast_channel *ast, char *rdest, int timeout);
7024 static int zt_hangup(struct ast_channel *ast);
7025 static int zt_answer(struct ast_channel *ast);
7026 @@ -732,6 +756,9 @@ static const struct ast_channel_tech zap
7027 .send_digit_begin = zt_digit_begin,
7028 .send_digit_end = zt_digit_end,
7029 .send_text = zt_sendtext,
7030 +#if 0 /* we (Debian) disable that addition because of ABI breakage */
7031 + .send_message = zt_sendmessage,
7034 .hangup = zt_hangup,
7035 .answer = zt_answer,
7036 @@ -1262,6 +1289,8 @@ static char *zap_sig2str(int sig)
7037 return "GR-303 with FXOKS";
7038 case SIG_GR303FXSKS:
7039 return "GR-303 with FXSKS";
7045 @@ -1683,7 +1712,7 @@ static inline int zt_confmute(struct zt_
7049 - if (p->sig == SIG_PRI) {
7050 + if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
7052 res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
7054 @@ -2098,6 +2127,25 @@ static int zt_call(struct ast_channel *a
7055 p->dialdest[0] = '\0';
7056 disable_dtmf_detect(p);
7060 + if (p->gsm.modul) {
7061 + c = strchr(dest, '/');
7066 + ast_mutex_lock(&p->gsm.lock);
7067 + if (gsm_dial(p->gsm.modul, p->use_callingpres ? ast->cid.cid_pres : 0, c)) {
7068 + ast_log(LOG_WARNING, "dialing failed on channel %d\n", p->channel);
7069 + ast_mutex_unlock(&p->gsm.lock);
7070 + ast_mutex_unlock(&p->lock);
7073 + ast_mutex_unlock(&p->gsm.lock);
7078 ast_log(LOG_DEBUG, "not yet implemented\n");
7079 ast_mutex_unlock(&p->lock);
7080 @@ -2737,7 +2785,13 @@ static int zt_hangup(struct ast_channel
7084 - if (p->sig && (p->sig != SIG_PRI))
7086 + if (p->gsm.modul) {
7087 + if (!p->alreadyhungup)
7088 + gsm_hangup(p->gsm.modul);
7091 + if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_GSM))
7092 res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
7094 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
7095 @@ -2914,6 +2968,13 @@ static int zt_answer(struct ast_channel
7101 + if (p->gsm.modul) {
7102 + gsm_answer(p->gsm.modul);
7107 ast_mutex_unlock(&p->lock);
7109 @@ -7302,6 +7363,10 @@ static int pri_create_spanmap(int span,
7114 +static void *gsm_dchannel(void *vgsm);
7117 static struct zt_pvt *mkintf(int channel, const struct zt_chan_conf *conf, struct zt_pri *pri, int reloading)
7119 /* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
7120 @@ -7530,6 +7595,37 @@ static struct zt_pvt *mkintf(int channel
7125 + if (conf->chan.sig == SIG_GSM) {
7126 + struct zt_bufferinfo bi;
7127 + ast_mutex_init(&tmp->gsm.lock);
7128 + strncpy(tmp->gsm.pin, gsm_modem_pin, sizeof(tmp->gsm.pin) - 1);
7129 + strncpy(tmp->gsm.exten, gsm_modem_exten, sizeof(tmp->gsm.exten) - 1);
7130 + tmp->gsm.available = 0;
7131 + snprintf(fn, sizeof(fn), "%d", channel + 1);
7132 + /* Open non-blocking */
7133 + tmp->gsm.fd = zt_open(fn);
7134 + bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
7135 + bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
7137 + bi.bufsize = 1024;
7138 + if (ioctl(tmp->gsm.fd, ZT_SET_BUFINFO, &bi)) {
7139 + ast_log(LOG_ERROR, "Unable to set buffer info on channel '%s': %s\n", fn, strerror(errno));
7142 + tmp->gsm.pvt = tmp;
7143 + tmp->gsm.span = tmp->span;
7144 + tmp->gsm.modul = gsm_new(tmp->gsm.fd, 0, tmp->gsm.pin, tmp->span, tmp->channel);
7145 + if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, tmp->channel)) {
7146 + ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d: %s\n", tmp->channel, strerror(errno));
7147 + destroy_zt_pvt(&tmp);
7150 + if (ast_pthread_create(&tmp->gsm.master, NULL, gsm_dchannel, &tmp->gsm)) {
7151 + zt_close(tmp->gsm.fd);
7156 conf->chan.sig = tmp->sig;
7157 conf->chan.radio = tmp->radio;
7158 @@ -7819,6 +7915,12 @@ static inline int available(struct zt_pv
7163 + if (p->gsm.modul) {
7164 + return gsm_available(p->gsm.modul);
7168 if (!(p->radio || (p->oprmode < 0)))
7170 if (!p->sig || (p->sig == SIG_FXSLS))
7171 @@ -8176,6 +8278,235 @@ next:
7176 +static int zt_reset_span(int span, int sleep) {
7180 + ctl = open("/dev/zap/ctl", O_RDWR);
7182 + ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
7185 + ast_verbose(VERBOSE_PREFIX_2 "Shutting down span %d. Please wait...\n", span);
7186 + res = ioctl(ctl, ZT_SHUTDOWN, &span);
7188 + ast_log(LOG_WARNING, "error shutting down span %d\n", span);
7191 + usleep(sleep * 1000);
7192 + ast_verbose(VERBOSE_PREFIX_2 "Starting up span %d. Please wait...\n", span);
7193 + res = ioctl(ctl, ZT_STARTUP, &span);
7195 + ast_log(LOG_WARNING, "error starting up span %d\n", span);
7198 + ast_verbose(VERBOSE_PREFIX_2 "Reset of span %d completed.\n", span);
7203 +static void handle_gsm_event(struct zt_gsm *gsm, gsm_event *e)
7205 + struct ast_channel *c = NULL;
7206 + int law = ZT_LAW_ALAW;
7210 + case GSM_EVENT_DCHAN_UP:
7211 + if (option_verbose > 2)
7212 + ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d registered to network!\n", gsm->span);
7213 + gsm->available = 1;
7215 + case GSM_EVENT_DCHAN_DOWN:
7216 + if (option_verbose > 2)
7217 + ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d unregistered from network!\n", gsm->span);
7218 + gsm->available = 0;
7219 +/* ast_mutex_lock(&gsm->pvt->lock);
7220 + gsm->pvt->alreadyhungup = 1;
7221 + if (gsm->pvt->owner) {
7222 + gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7224 + ast_mutex_unlock(&gsm->pvt->lock); */
7226 + case GSM_EVENT_RING:
7227 + ast_mutex_lock(&gsm->pvt->lock);
7228 + if (!ast_strlen_zero(e->ring.callingnum)) {
7229 + strncpy(gsm->pvt->cid_num, e->ring.callingnum, sizeof(gsm->pvt->cid_num) - 1);
7231 + strncpy(gsm->pvt->cid_name, "CID withheld", sizeof(gsm->pvt->cid_name));
7233 + if (!ast_strlen_zero(gsm->exten)) {
7234 + strncpy(gsm->pvt->exten, gsm->exten, sizeof(gsm->pvt->exten) - 1);
7236 + gsm->pvt->exten[0] = 's';
7237 + gsm->pvt->exten[1] = '\0';
7239 + c = zt_new(gsm->pvt, AST_STATE_RING, 1, SUB_REAL, ZT_LAW_ALAW, AST_TRANS_CAP_SPEECH);
7241 + if (option_verbose > 2)
7242 + ast_verbose(VERBOSE_PREFIX_3 "Ring on channel %d (from %s to %s)\n", e->ring.channel, e->ring.callingnum, gsm->exten);
7243 + gsm->pvt->owner = c;
7244 + if (ioctl(gsm->pvt->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
7245 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", gsm->pvt->channel, law);
7246 + res = zt_setlaw(gsm->pvt->subs[SUB_REAL].zfd, law);
7247 + res = set_actual_gain(gsm->pvt->subs[SUB_REAL].zfd, 0, gsm->pvt->rxgain, gsm->pvt->txgain, law);
7249 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", gsm->pvt->channel);
7251 +// ast_log(LOG_NOTICE, "tx gain %f rx gain %f law %d pvt->law %d\n", gsm->pvt->txgain, gsm->pvt->rxgain, law, gsm->pvt->law);
7254 + ast_mutex_unlock(&gsm->pvt->lock);
7256 + case GSM_EVENT_HANGUP:
7257 + ast_verbose(VERBOSE_PREFIX_3 "Got hang up on channel %d\n", e->hangup.channel);
7258 + ast_mutex_lock(&gsm->pvt->lock);
7259 + gsm->pvt->alreadyhungup = 1;
7260 + if (gsm->pvt->owner) {
7261 + gsm->pvt->owner->hangupcause = e->hangup.cause;
7262 + gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7264 + ast_mutex_unlock(&gsm->pvt->lock);
7266 + case GSM_EVENT_ERROR:
7267 + ast_log(LOG_WARNING, "Got error on channel\n");
7268 + ast_mutex_lock(&gsm->pvt->lock);
7269 + gsm->pvt->alreadyhungup = 1;
7270 + if (gsm->pvt->owner) {
7271 + gsm->pvt->owner->hangupcause = e->error.cause;
7272 + gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7274 + ast_mutex_unlock(&gsm->pvt->lock);
7275 + if (e->error.hard) {
7276 +// gsm_poweroff(gsm->modul);
7277 + zt_reset_span(gsm->span, 8000);
7278 +// gsm_restart(gsm->modul, 10000);
7280 +// gsm_poweroff(gsm->modul);
7281 + zt_reset_span(gsm->span, 8000);
7282 +// gsm_restart(gsm->modul, 10000);
7285 + case GSM_EVENT_ALERTING:
7286 + ast_mutex_lock(&gsm->pvt->lock);
7287 + gsm->pvt->subs[SUB_REAL].needringing =1;
7288 + ast_mutex_unlock(&gsm->pvt->lock);
7290 + case GSM_EVENT_ANSWER:
7291 + ast_mutex_lock(&gsm->pvt->lock);
7292 + gsm->pvt->dialing = 0;
7293 + gsm->pvt->subs[SUB_REAL].needanswer =1;
7294 + gsm->pvt->ignoredtmf = 0;
7295 + ast_mutex_unlock(&gsm->pvt->lock);
7297 + case GSM_EVENT_PIN_REQUIRED:
7298 + gsm_send_pin(gsm->modul, gsm->pin);
7300 + case GSM_EVENT_SM_RECEIVED:
7301 + ast_verbose(VERBOSE_PREFIX_3 "SMS from %s received on span %d. (Text: %s) (PDU: %s)\n", e->sm_received.sender, gsm->span, e->sm_received.text, e->sm_received.pdu);
7302 + manager_event(EVENT_FLAG_CALL, "Message received",
7310 + e->sm_received.sender,
7311 + e->sm_received.smsc,
7312 + e->sm_received.len,
7313 + e->sm_received.text,
7314 + e->sm_received.pdu);
7317 + ast_log(LOG_WARNING,"!! Unknown GSM event %d !!\n", e->e);
7321 +static void *gsm_dchannel(void *vgsm)
7323 + struct zt_gsm *gsm = vgsm;
7325 + struct timeval tv = {0,0}, *next;
7326 + fd_set rfds, efds;
7329 + if (!gsm) return NULL;
7331 + if (!gsm->modul) {
7332 + fprintf(stderr, "No gsm_mod\n");
7335 + gsm_set_debug(gsm->modul, GSM_DEBUG_NONE);
7338 + /* Run the D-Channel */
7341 + FD_SET(gsm->fd, &rfds);
7342 + FD_SET(gsm->fd, &efds);
7344 + if ((next = gsm_schedule_next(gsm->modul))) {
7345 + gettimeofday(&tv, NULL);
7346 + tv.tv_sec = next->tv_sec - tv.tv_sec;
7347 + tv.tv_usec = next->tv_usec - tv.tv_usec;
7348 + if (tv.tv_usec < 0) {
7349 + tv.tv_usec += 1000000;
7352 + if (tv.tv_sec < 0) {
7357 + res = select(gsm->fd + 1, &rfds, NULL, &efds, next ? &tv : NULL);
7360 + ast_mutex_lock(&gsm->lock);
7362 + e = gsm_schedule_run(gsm->modul);
7363 + } else if (res > 0) {
7364 + e = gsm_check_event(gsm->modul, 1);
7365 + } else if (errno == ELAST) {
7366 + res = ioctl(gsm->fd, ZT_GETEVENT, &x);
7367 + printf("Got Zaptel event: %d\n", x);
7368 + } else if (errno != EINTR)
7369 + fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
7372 + e = gsm_check_event(gsm->modul, 0);
7376 + handle_gsm_event(gsm, e);
7378 + ast_mutex_unlock(&gsm->lock);
7380 + res = ioctl(gsm->fd, ZT_GETEVENT, &x);
7384 + case ZT_EVENT_NOALARM:
7385 + ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", gsm->span);
7387 + gsm_restart(gsm->modul, 10000);
7389 + case ZT_EVENT_ALARM:
7390 + ast_log(LOG_NOTICE, "Alarm detected on span %d\n", gsm->span);
7393 + fprintf(stderr, "Got event on GSM interface: %d\n", x);
7405 static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
7407 @@ -8450,6 +8781,18 @@ static void zt_pri_error(char *s, int sp
7408 ast_log(LOG_WARNING, "%d %s", span, s);
7412 +static void zt_gsm_message(char *s, int channel)
7414 + ast_verbose("GSM %d: %s", channel, s);
7417 +static void zt_gsm_error(char *s, int channel)
7419 + ast_log(LOG_WARNING, "GSM %d: %s", channel, s);
7423 static int pri_check_restart(struct zt_pri *pri)
7425 if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
7426 @@ -10868,6 +11211,243 @@ static int app_zapInband(struct ast_chan
7428 #endif /* HAVE_PRI */
7431 +static int handle_zap_reset_span(int fd, int argc, char *argv[])
7436 + return RESULT_SHOWUSAGE;
7437 + span = atoi(argv[3]);
7438 + if ((span < 1) || (span > NUM_SPANS)) {
7439 + ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
7440 + return RESULT_SUCCESS;
7442 + if (zt_reset_span(span, sleep)) {
7443 + return RESULT_FAILURE;
7445 + return RESULT_SUCCESS;
7448 +static int handle_gsm_debug_helper(int fd, int channel, int debug)
7450 +/* gsm debug channel <channel> */
7451 + struct zt_pvt *pvt = NULL;
7452 + if (channel < 1) {
7453 + ast_cli(fd, "Invalid channel %d. Should be a number.\n", channel);
7454 + return RESULT_SUCCESS;
7458 + if (pvt->channel == channel) {
7459 + ast_mutex_lock(&pvt->lock);
7460 + gsm_set_debug(pvt->gsm.modul, debug);
7461 + ast_mutex_unlock(&pvt->lock);
7462 + ast_cli(fd, "%s debugging on channel %d\n", debug ? "Enabled":"Disabled", channel);
7463 + return RESULT_SUCCESS;
7468 + ast_cli(fd, "No GSM running on channel %d\n", channel);
7469 + return RESULT_SUCCESS;
7474 +static int handle_gsm_debug(int fd, int argc, char *argv[])
7476 +/* gsm debug channel <channel> */
7479 + return RESULT_SHOWUSAGE;
7481 + channel = atoi(argv[3]);
7482 + return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_AT);
7485 +static int handle_gsm_no_debug(int fd, int argc, char *argv[])
7487 +/* gsm no debug channel <channel> */
7490 + return RESULT_SHOWUSAGE;
7492 + channel = atoi(argv[4]);
7493 + return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_NONE);
7496 +static char zap_reset_help[] =
7497 + "Usage: zap reset span <span>\n"
7498 + " Reset/Restart a zaptel span\n";
7500 +static char gsm_debug_help[] =
7501 + "Usage: gsm debug channel <channel>\n"
7502 + " Enables debugging on a given GSM channel\n";
7504 +static char gsm_no_debug_help[] =
7505 + "Usage: gsm no debug channel <channel>\n"
7506 + " Disables debugging on a given GSM channel\n";
7508 +static struct ast_cli_entry zap_gsm_cli[] = {
7509 + { { "zap", "reset", "span", NULL }, handle_zap_reset_span,
7510 + "Restart a zaptel span", zap_reset_help, complete_span_4 },
7511 + { { "gsm", "debug", "channel", NULL }, handle_gsm_debug,
7512 + "Enables GSM debugging on a channel", gsm_debug_help },
7513 + { { "gsm", "no", "debug", "channel", NULL }, handle_gsm_no_debug,
7514 + "Disables GSM debugging on a channel", gsm_no_debug_help},
7519 +static char gsm_send_pdu_help[] =
7520 + "Usage: gsm send pdu <channel> <pdu>\n"
7521 + " Sends a PDU on a GSM channel\n";
7525 +static int handle_gsm_send_pdu(int fd, int argc, char *argv[])
7527 +/* gsm send sms <channel> <destination> <message> */
7529 + struct zt_pvt *pvt = NULL;
7531 + return RESULT_SHOWUSAGE;
7533 + channel = atoi(argv[3]);
7534 + if (channel < 1) {
7535 + ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
7536 + return RESULT_SUCCESS;
7540 + if (pvt->channel == channel) {
7542 + ast_cli(fd, "Channel in use.\n");
7543 + return RESULT_FAILURE;
7545 + ast_mutex_lock(&pvt->lock);
7546 + gsm_sms_send_pdu(pvt->gsm.modul, argv[4]);
7547 + ast_mutex_unlock(&pvt->lock);
7548 + return RESULT_SUCCESS;
7554 + return RESULT_SUCCESS;
7557 +static struct ast_cli_entry gsm_send_pdu = {
7558 + { "gsm", "send", "pdu", NULL }, handle_gsm_send_pdu, "Sends a SM on a GSM channel", gsm_send_pdu_help, complete_span_4 };
7561 +static char gsm_send_sms_help[] =
7562 + "Usage: gsm send sms <channel> <destination> <message>\n"
7563 + " Sends a SM on a GSM channel\n";
7566 +static int handle_gsm_send_sms(int fd, int argc, char *argv[])
7568 +/* gsm send sms <channel> <destination> <message> */
7570 + struct zt_pvt *pvt = NULL;
7572 + return RESULT_SHOWUSAGE;
7574 + channel = atoi(argv[3]);
7575 + if (channel < 1) {
7576 + ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
7577 + return RESULT_SUCCESS;
7581 + if (pvt->channel == channel) {
7583 + ast_cli(fd, "Channel in use.\n");
7584 + return RESULT_FAILURE;
7586 + ast_mutex_lock(&pvt->lock);
7587 + gsm_sms_send_text(pvt->gsm.modul, argv[4], argv[5]);
7588 + ast_mutex_unlock(&pvt->lock);
7589 + return RESULT_SUCCESS;
7595 + return RESULT_SUCCESS;
7598 +static int zt_gsm_sendtext(struct ast_channel *chan, const char * dest, const char *text, int ispdu) {
7599 + struct zt_pvt *pvt = NULL;
7601 + pvt = chan->tech_pvt;
7603 + if (!pvt) return -1;
7605 + /* parse dialstring */
7606 + c = strrchr(dest, '/');
7612 + ast_mutex_lock(&pvt->lock);
7614 + gsm_sms_send_pdu(pvt->gsm.modul, (char *)text);
7616 + gsm_sms_send_text(pvt->gsm.modul, c, (char *)text);
7618 + ast_mutex_unlock(&pvt->lock);
7619 + gsm_wait(pvt->gsm.modul);
7623 +static struct ast_cli_entry gsm_send_sms = {
7624 + { "gsm", "send", "sms", NULL }, handle_gsm_send_sms, "Sends a SM on a GSM channel", gsm_send_sms_help, complete_span_4 };
7626 +static char gsm_show_status_help[] =
7627 + "Usage: gsm show status <channel>>\n"
7628 + " Displays status information about the GSM channel.\n";
7631 +static int handle_gsm_show_status(int fd, int argc, char *argv[])
7634 + struct zt_pvt *pvt = NULL;
7636 + return RESULT_SHOWUSAGE;
7638 + channel = atoi(argv[3]);
7639 + if (channel < 1) {
7640 + ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
7641 + return RESULT_SUCCESS;
7645 + if (pvt->channel == channel) {
7647 + ast_cli(fd, "Channel in use.\n");
7648 + return RESULT_FAILURE;
7650 + ast_mutex_lock(&pvt->lock);
7651 + gsm_request_status(pvt->gsm.modul);
7652 + ast_mutex_unlock(&pvt->lock);
7653 + return RESULT_SUCCESS;
7659 + return RESULT_SUCCESS;
7662 +static struct ast_cli_entry gsm_show_status = {
7663 + { "gsm", "show", "status", NULL }, handle_gsm_show_status, "Displays status information about the GSM channel.", gsm_show_status_help, complete_span_4 };
7665 +#endif /* HAVE_GSMAT */
7667 static int app_zapEC(struct ast_channel *chan, void *data)
7670 @@ -11489,6 +12069,12 @@ static int __unload_module(void)
7671 ast_unregister_application(zapCD_app);
7672 ast_unregister_application(zapInband_app);
7675 + ast_cli_unregister_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
7676 + ast_cli_unregister(&gsm_send_sms);
7677 + ast_cli_unregister(&gsm_send_pdu);
7678 + ast_cli_unregister(&gsm_show_status);
7680 ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
7681 ast_unregister_application(zapEC_app);
7682 ast_manager_unregister( "ZapDialOffhook" );
7683 @@ -12009,6 +12595,11 @@ static int process_zap(struct zt_chan_co
7684 confp->chan.radio = 0;
7685 confp->pri.nodetype = BRI_CPE;
7688 + } else if (!strcasecmp(v->value, "gsm")) {
7689 + confp->chan.sig = SIG_GSM;
7690 + confp->chan.radio = 0;
7693 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
7695 @@ -12151,6 +12742,10 @@ static int process_zap(struct zt_chan_co
7696 ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
7697 } else if (!strcasecmp(v->name, "withheldcid")) {
7698 ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
7699 + } else if (!strcasecmp(v->name, "pin")) {
7700 + ast_copy_string(gsm_modem_pin, v->value, sizeof(gsm_modem_pin) - 1);
7701 + } else if (!strcasecmp(v->name, "exten")) {
7702 + ast_copy_string(gsm_modem_exten, v->value, sizeof(gsm_modem_exten) - 1);
7703 } else if (!strcasecmp(v->name, "resetinterval")) {
7704 if (!strcasecmp(v->value, "never"))
7705 confp->pri.resetinterval = -1;
7706 @@ -12506,6 +13101,10 @@ static int load_module(void)
7707 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
7708 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
7711 + gsm_set_error(zt_gsm_error);
7712 + gsm_set_message(zt_gsm_message);
7715 /* Make sure we can register our Zap channel type */
7717 @@ -12524,6 +13123,12 @@ static int load_module(void)
7719 ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
7720 ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
7722 + ast_cli_register(&gsm_send_sms);
7723 + ast_cli_register(&gsm_send_pdu);
7724 + ast_cli_register(&gsm_show_status);
7725 + ast_cli_register_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
7728 memset(round_robin, 0, sizeof(round_robin));
7729 ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
7730 @@ -12537,7 +13142,66 @@ static int load_module(void)
7734 -static int zt_sendtext(struct ast_channel *c, const char *text)
7736 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text);
7738 +static int zt_pri_sendtext(struct ast_channel *c, const char *text) {
7739 + struct zt_pvt *p = c->tech_pvt;
7740 + if (!p) return -1;
7741 + if (!p->pri) return -1;
7742 + if (strlen(text)) {
7744 + if (!pri_grab(p, p->pri)) {
7745 + // ast_log(LOG_NOTICE, "Sending Display IE '%s'\n", text);
7746 + pri_information_display(p->pri->pri,p->call,(char *)text);
7748 + } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7755 +static int zt_sendtext(struct ast_channel *c, const char *text) {
7756 + struct zt_pvt *p = c->tech_pvt;
7757 + if (!p) return -1;
7758 + if (p->sig == SIG_PRI) {
7760 + return zt_pri_sendtext(c, text);
7762 + } else if (p->sig == SIG_GSM) {
7764 + return zt_tdd_sendtext(c, text);
7769 +static int zt_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu) {
7770 +struct zt_pvt *p = c->tech_pvt;
7771 + if (!p) return -1;
7772 + if (p->sig == SIG_PRI) {
7775 + ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP ISDN channel\n");
7778 + return zt_pri_sendtext(c, text);
7780 + } else if (p->sig == SIG_GSM) {
7782 + return zt_gsm_sendtext(c, dest, text, ispdu);
7786 + ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP channel\n");
7789 + return zt_tdd_sendtext(c, text);
7794 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text)
7796 #define END_SILENCE_LEN 400
7797 #define HEADER_MS 50
7800 @@ -178,6 +178,7 @@ AST_EXT_LIB_SETUP([CAP], [POSIX 1.e capa
7801 AST_EXT_LIB_SETUP([CURSES], [curses], [curses])
7802 AST_EXT_LIB_SETUP([GNUTLS], [GNU TLS support (used for iksemel only)], [gnutls])
7803 AST_EXT_LIB_SETUP([GSM], [GSM], [gsm], [, or 'internal'])
7804 +AST_EXT_LIB_SETUP([GSMAT], [GSMAT], [GSM AT command signalling], [gsmat])
7805 AST_EXT_LIB_SETUP([IKSEMEL], [Iksemel Jabber Library], [iksemel])
7806 AST_EXT_LIB_SETUP([IMAP_TK], [UW IMAP Toolkit], [imap])
7807 AST_EXT_LIB_SETUP([ISDNNET], [ISDN4Linux Library], [isdnnet])
7810 @@ -26600,6 +26600,188 @@ echo "$as_me: *** without explicitly spe
7814 +{ echo "$as_me:$LINENO: checking for ${GSMAT_DIR}/include/libgsmat.h" >&5
7815 +echo $ECHO_N "checking for ${GSMAT_DIR}/include/libgsmat.h... $ECHO_C" >&6; }
7816 +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
7817 + echo $ECHO_N "(cached) $ECHO_C" >&6
7819 + eval "$as_ac_Header=\$ac_header_preproc"
7821 +ac_res=`eval echo '${'$as_ac_Header'}'`
7822 + { echo "$as_me:$LINENO: result: $ac_res" >&5
7823 +echo "${ECHO_T}$ac_res" >&6; }
7825 +if test `eval echo '${'$as_ac_Header'}'` = yes; then
7826 + GSMAT_HEADER_FOUND=1
7828 + GSMAT_HEADER_FOUND=0
7833 + if test "${GSMAT_HEADER_FOUND}" = "yes"; then
7834 + GSMAT_LIB="-lgsmat "
7835 + GSMAT_HEADER_FOUND="1"
7836 + if test "x${GSMAT_DIR}" != "x"; then
7837 + GSMAT_LIB="${pbxlibdir} ${GSMAT_LIB}"
7838 + GSMAT_INCLUDE="-I${GSMAT_DIR}/include"
7840 + CPPFLAGS="${saved_cppflags}"
7842 + if test "xlibgsmat.h" != "x" ; then
7843 + if test "${ac_cv_header_libpri_h+set}" = set; then
7844 + { echo "$as_me:$LINENO: checking for libgsmat.h" >&5
7845 +echo $ECHO_N "checking for libgsmat.h... $ECHO_C" >&6; }
7846 +if test "${ac_cv_header_libgsmat_h+set}" = set; then
7847 + echo $ECHO_N "(cached) $ECHO_C" >&6
7849 +{ echo "$as_me:$LINENO: result: $ac_cv_header_libgsmat_h" >&5
7850 +echo "${ECHO_T}$ac_cv_header_libgsmat_h" >&6; }
7852 + # Is the header compilable?
7853 +{ echo "$as_me:$LINENO: checking libgsmat.h usability" >&5
7854 +echo $ECHO_N "checking libgsmat.h usability... $ECHO_C" >&6; }
7855 +cat >conftest.$ac_ext <<_ACEOF
7858 +cat confdefs.h >>conftest.$ac_ext
7859 +cat >>conftest.$ac_ext <<_ACEOF
7860 +/* end confdefs.h. */
7861 +$ac_includes_default
7862 +#include <libgsmat.h>
7864 +rm -f conftest.$ac_objext
7865 +if { (ac_try="$ac_compile"
7866 +case "(($ac_try" in
7867 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
7868 + *) ac_try_echo=$ac_try;;
7870 +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
7871 + (eval "$ac_compile") 2>conftest.er1
7873 + grep -v '^ *+' conftest.er1 >conftest.err
7874 + rm -f conftest.er1
7875 + cat conftest.err >&5
7876 + echo "$as_me:$LINENO: \$? = $ac_status" >&5
7877 + (exit $ac_status); } && {
7878 + test -z "$ac_c_werror_flag" ||
7879 + test ! -s conftest.err
7880 + } && test -s conftest.$ac_objext; then
7881 + ac_header_compiler=yes
7883 + echo "$as_me: failed program was:" >&5
7884 +sed 's/^/| /' conftest.$ac_ext >&5
7886 + ac_header_compiler=no
7889 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
7890 +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
7891 +echo "${ECHO_T}$ac_header_compiler" >&6; }
7893 +# Is the header present?
7894 +{ echo "$as_me:$LINENO: checking libgsmat.h presence" >&5
7895 +echo $ECHO_N "checking libgsmat.h presence... $ECHO_C" >&6; }
7896 +cat >conftest.$ac_ext <<_ACEOF
7899 +cat confdefs.h >>conftest.$ac_ext
7900 +cat >>conftest.$ac_ext <<_ACEOF
7901 +/* end confdefs.h. */
7902 +#include <libgsmat.h>
7904 +if { (ac_try="$ac_cpp conftest.$ac_ext"
7905 +case "(($ac_try" in
7906 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
7907 + *) ac_try_echo=$ac_try;;
7909 +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
7910 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
7912 + grep -v '^ *+' conftest.er1 >conftest.err
7913 + rm -f conftest.er1
7914 + cat conftest.err >&5
7915 + echo "$as_me:$LINENO: \$? = $ac_status" >&5
7916 + (exit $ac_status); } >/dev/null && {
7917 + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
7918 + test ! -s conftest.err
7920 + ac_header_preproc=yes
7922 + echo "$as_me: failed program was:" >&5
7923 +sed 's/^/| /' conftest.$ac_ext >&5
7925 + ac_header_preproc=no
7928 +rm -f conftest.err conftest.$ac_ext
7929 +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
7930 +echo "${ECHO_T}$ac_header_preproc" >&6; }
7932 +# So? What about this header?
7933 +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
7935 + { echo "$as_me:$LINENO: WARNING: libgsmat.h: accepted by the compiler, rejected by the preprocessor!" >&5
7936 +echo "$as_me: WARNING: libgsmat.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
7937 + { echo "$as_me:$LINENO: WARNING: libgsmat.h: proceeding with the compiler's result" >&5
7938 +echo "$as_me: WARNING: libgsmat.h: proceeding with the compiler's result" >&2;}
7939 + ac_header_preproc=yes
7942 + { echo "$as_me:$LINENO: WARNING: libgsmat.h: present but cannot be compiled" >&5
7943 +echo "$as_me: WARNING: libgsmat.h: present but cannot be compiled" >&2;}
7944 + { echo "$as_me:$LINENO: WARNING: libgsmat.h: check for missing prerequisite headers?" >&5
7945 +echo "$as_me: WARNING: libgsmat.h: check for missing prerequisite headers?" >&2;}
7946 + { echo "$as_me:$LINENO: WARNING: libgsmat.h: see the Autoconf documentation" >&5
7947 +echo "$as_me: WARNING: libgsmat.h: see the Autoconf documentation" >&2;}
7948 + { echo "$as_me:$LINENO: WARNING: libgsmat.h: section \"Present But Cannot Be Compiled\"" >&5
7949 +echo "$as_me: WARNING: libgsmat.h: section \"Present But Cannot Be Compiled\"" >&2;}
7950 + { echo "$as_me:$LINENO: WARNING: libgsmat.h: proceeding with the preprocessor's result" >&5
7951 +echo "$as_me: WARNING: libgsmat.h: proceeding with the preprocessor's result" >&2;}
7952 + { echo "$as_me:$LINENO: WARNING: libgsmat.h: in the future, the compiler will take precedence" >&5
7953 +echo "$as_me: WARNING: libgsmat.h: in the future, the compiler will take precedence" >&2;}
7957 +{ echo "$as_me:$LINENO: checking for libgsmat.h" >&5
7958 +echo $ECHO_N "checking for libgsmat.h... $ECHO_C" >&6; }
7959 +if test "${ac_cv_header_libgsmat_h+set}" = set; then
7960 + echo $ECHO_N "(cached) $ECHO_C" >&6
7962 + ac_cv_header_libgsmat_h=$ac_header_preproc
7964 +{ echo "$as_me:$LINENO: result: $ac_cv_header_libgsmat_h" >&5
7965 +echo "${ECHO_T}$ac_cv_header_libgsmat_h" >&6; }
7972 + if test "x${GSMAT_HEADER_FOUND}" = "x0" ; then
7973 + if test -n "${GSMAT_MANDATORY}" ;
7975 + { echo "$as_me:$LINENO: ***" >&5
7976 +echo "$as_me: ***" >&6;}
7977 + { echo "$as_me:$LINENO: *** It appears that you do not have the GSMAT development package installed." >&5
7978 +echo "$as_me: *** It appears that you do not have the GSMAT development package installed." >&6;}
7979 + { echo "$as_me:$LINENO: *** Please install it to include ${GSMAT_DESCRIP} support, or re-run configure" >&5
7980 +echo "$as_me: *** Please install it to include ${GSMAT_DESCRIP} support, or re-run configure" >&6;}
7981 + { echo "$as_me:$LINENO: *** without explicitly specifying --with-${GSMAT_OPTION}" >&5
7982 +echo "$as_me: *** without explicitly specifying --with-${GSMAT_OPTION}" >&6;}
7991 +cat >>confdefs.h <<_ACEOF
7992 +#define HAVE_GSMAT 1
7997 if test "${USE_PWLIB}" != "no"; then
7998 if test -n "${PWLIB_DIR}"; then