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