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