Merged revisions 114191 via svnmerge from
[asterisk/asterisk.git] / apps / app_chanspy.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2005 Anthony Minessale II (anthmct@yahoo.com)
5  * Copyright (C) 2005 - 2008, Digium, Inc.
6  *
7  * A license has been granted to Digium (via disclaimer) for the use of
8  * this code.
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20
21 /*! \file
22  *
23  * \brief ChanSpy: Listen in on any channel.
24  *
25  * \author Anthony Minessale II <anthmct@yahoo.com>
26  * \author Joshua Colp <jcolp@digium.com>
27  * \author Russell Bryant <russell@digium.com>
28  *
29  * \ingroup applications
30  */
31
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include <ctype.h>
37
38 #include "asterisk/paths.h" /* use ast_config_AST_MONITOR_DIR */
39 #include "asterisk/file.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/audiohook.h"
42 #include "asterisk/features.h"
43 #include "asterisk/app.h"
44 #include "asterisk/utils.h"
45 #include "asterisk/say.h"
46 #include "asterisk/pbx.h"
47 #include "asterisk/translate.h"
48 #include "asterisk/module.h"
49 #include "asterisk/lock.h"
50
51 #define AST_NAME_STRLEN 256
52
53 static const char *tdesc = "Listen to a channel, and optionally whisper into it";
54 static const char *app_chan = "ChanSpy";
55 static const char *desc_chan =
56 "  ChanSpy([chanprefix][,options]): This application is used to listen to the\n"
57 "audio from an Asterisk channel. This includes the audio coming in and\n"
58 "out of the channel being spied on. If the 'chanprefix' parameter is specified,\n"
59 "only channels beginning with this string will be spied upon.\n"
60 "  While spying, the following actions may be performed:\n"
61 "    - Dialing # cycles the volume level.\n"
62 "    - Dialing * will stop spying and look for another channel to spy on.\n"
63 "    - Dialing a series of digits followed by # builds a channel name to append\n"
64 "      to 'chanprefix'. For example, executing ChanSpy(Agent) and then dialing\n"
65 "      the digits '1234#' while spying will begin spying on the channel\n"
66 "      'Agent/1234'.\n"
67 "  Note: The X option supersedes the three features above in that if a valid\n"
68 "        single digit extension exists in the correct context ChanSpy will\n"
69 "        exit to it. This also disables choosing a channel based on 'chanprefix'\n"
70 "        and a digit sequence.\n"
71 "  Options:\n"
72 "    b             - Only spy on channels involved in a bridged call.\n"
73 "    g(grp)        - Match only channels where their SPYGROUP variable is set to\n"
74 "                    contain 'grp' in an optional : delimited list.\n"
75 "    q             - Don't play a beep when beginning to spy on a channel, or speak the\n"
76 "                    selected channel name.\n"
77 "    r[(basename)] - Record the session to the monitor spool directory. An\n"
78 "                    optional base for the filename may be specified. The\n"
79 "                    default is 'chanspy'.\n"
80 "    s             - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n"
81 "                    speaking the selected channel name.\n"
82 "    v([value])    - Adjust the initial volume in the range from -4 to 4. A\n"
83 "                    negative value refers to a quieter setting.\n"
84 "    w             - Enable 'whisper' mode, so the spying channel can talk to\n"
85 "                    the spied-on channel.\n"
86 "    W             - Enable 'private whisper' mode, so the spying channel can\n"
87 "                    talk to the spied-on channel but cannot listen to that\n"
88 "                    channel.\n"
89 "    o             - Only listen to audio coming from this channel.\n"
90 "    X             - Allow the user to exit ChanSpy to a valid single digit\n"
91 "                    numeric extension in the current context or the context\n"
92 "                    specified by the SPY_EXIT_CONTEXT channel variable. The\n"
93 "                    name of the last channel that was spied on will be stored\n"
94 "                    in the SPY_CHANNEL variable.\n"
95 "    e(ext)        - Enable 'enforced' mode, so the spying channel can\n"
96 "                    only monitor extensions whose name is in the 'ext' : \n"
97 "                    delimited list.\n"
98 ;
99
100 static const char *app_ext = "ExtenSpy";
101 static const char *desc_ext =
102 "  ExtenSpy(exten[@context][,options]): This application is used to listen to the\n"
103 "audio from an Asterisk channel. This includes the audio coming in and\n"
104 "out of the channel being spied on. Only channels created by outgoing calls for the\n"
105 "specified extension will be selected for spying. If the optional context is not\n"
106 "supplied, the current channel's context will be used.\n"
107 "  While spying, the following actions may be performed:\n"
108 "    - Dialing # cycles the volume level.\n"
109 "    - Dialing * will stop spying and look for another channel to spy on.\n"
110 "  Note: The X option superseeds the two features above in that if a valid\n"
111 "        single digit extension exists in the correct context it ChanSpy will\n"
112 "        exit to it.\n"
113 "  Options:\n"
114 "    b             - Only spy on channels involved in a bridged call.\n"
115 "    g(grp)        - Match only channels where their ${SPYGROUP} variable is set to\n"
116 "                    contain 'grp' in an optional : delimited list.\n"
117 "    q             - Don't play a beep when beginning to spy on a channel, or speak the\n"
118 "                    selected channel name.\n"
119 "    r[(basename)] - Record the session to the monitor spool directory. An\n"
120 "                    optional base for the filename may be specified. The\n"
121 "                    default is 'chanspy'.\n"
122 "    s             - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n"
123 "                    speaking the selected channel name.\n"
124 "    v([value])    - Adjust the initial volume in the range from -4 to 4. A\n"
125 "                    negative value refers to a quieter setting.\n"
126 "    w             - Enable 'whisper' mode, so the spying channel can talk to\n"
127 "                    the spied-on channel.\n"
128 "    W             - Enable 'private whisper' mode, so the spying channel can\n"
129 "                    talk to the spied-on channel but cannot listen to that\n"
130 "                    channel.\n"
131 "    o             - Only listen to audio coming from this channel.\n"
132 "    X             - Allow the user to exit ChanSpy to a valid single digit\n"
133 "                    numeric extension in the current context or the context\n"
134 "                    specified by the SPY_EXIT_CONTEXT channel variable. The\n"
135 "                    name of the last channel that was spied on will be stored\n"
136 "                    in the SPY_CHANNEL variable.\n"
137 ;
138
139 enum {
140         OPTION_QUIET     = (1 << 0),    /* Quiet, no announcement */
141         OPTION_BRIDGED   = (1 << 1),    /* Only look at bridged calls */
142         OPTION_VOLUME    = (1 << 2),    /* Specify initial volume */
143         OPTION_GROUP     = (1 << 3),    /* Only look at channels in group */
144         OPTION_RECORD    = (1 << 4),
145         OPTION_WHISPER   = (1 << 5),
146         OPTION_PRIVATE   = (1 << 6),    /* Private Whisper mode */
147         OPTION_READONLY  = (1 << 7),    /* Don't mix the two channels */
148         OPTION_EXIT      = (1 << 8),    /* Exit to a valid single digit extension */
149         OPTION_ENFORCED  = (1 << 9),    /* Enforced mode */
150         OPTION_NOTECH    = (1 << 10),   /* Skip technology name playback */
151 } chanspy_opt_flags;
152
153 enum {
154         OPT_ARG_VOLUME = 0,
155         OPT_ARG_GROUP,
156         OPT_ARG_RECORD,
157         OPT_ARG_ENFORCED,
158         OPT_ARG_ARRAY_SIZE,
159 } chanspy_opt_args;
160
161 AST_APP_OPTIONS(spy_opts, {
162         AST_APP_OPTION('q', OPTION_QUIET),
163         AST_APP_OPTION('b', OPTION_BRIDGED),
164         AST_APP_OPTION('w', OPTION_WHISPER),
165         AST_APP_OPTION('W', OPTION_PRIVATE),
166         AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
167         AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP),
168         AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
169         AST_APP_OPTION_ARG('e', OPTION_ENFORCED, OPT_ARG_ENFORCED),
170         AST_APP_OPTION('o', OPTION_READONLY),
171         AST_APP_OPTION('X', OPTION_EXIT),
172         AST_APP_OPTION('s', OPTION_NOTECH),
173 });
174
175
176 struct chanspy_translation_helper {
177         /* spy data */
178         struct ast_audiohook spy_audiohook;
179         struct ast_audiohook whisper_audiohook;
180         int fd;
181         int volfactor;
182 };
183
184 static void *spy_alloc(struct ast_channel *chan, void *data)
185 {
186         /* just store the data pointer in the channel structure */
187         return data;
188 }
189
190 static void spy_release(struct ast_channel *chan, void *data)
191 {
192         /* nothing to do */
193 }
194
195 static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
196 {
197         struct chanspy_translation_helper *csth = data;
198         struct ast_frame *f = NULL;
199
200         ast_audiohook_lock(&csth->spy_audiohook);
201         if (csth->spy_audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
202                 /* Channel is already gone more than likely */
203                 ast_audiohook_unlock(&csth->spy_audiohook);
204                 return -1;
205         }
206
207         f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR);
208
209         ast_audiohook_unlock(&csth->spy_audiohook);
210
211         if (!f)
212                 return 0;
213
214         if (ast_write(chan, f)) {
215                 ast_frfree(f);
216                 return -1;
217         }
218
219         if (csth->fd)
220                 write(csth->fd, f->data, f->datalen);
221
222         ast_frfree(f);
223
224         return 0;
225 }
226
227 static struct ast_generator spygen = {
228         .alloc = spy_alloc,
229         .release = spy_release,
230         .generate = spy_generate,
231 };
232
233 static int start_spying(struct ast_channel *chan, const char *spychan_name, struct ast_audiohook *audiohook) 
234 {
235         int res = 0;
236         struct ast_channel *peer = NULL;
237
238         ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, chan->name);
239
240         res = ast_audiohook_attach(chan, audiohook);
241
242         if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) {
243                 ast_channel_unlock(chan);
244                 ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
245         } else
246                 ast_channel_unlock(chan);
247
248         return res;
249 }
250
251 struct chanspy_ds {
252         struct ast_channel *chan;
253         ast_mutex_t lock;
254 };
255
256 static int channel_spy(struct ast_channel *chan, struct chanspy_ds *spyee_chanspy_ds, 
257         int *volfactor, int fd, const struct ast_flags *flags, char *exitcontext) 
258 {
259         struct chanspy_translation_helper csth;
260         int running = 0, res, x = 0;
261         char inp[24] = {0};
262         char *name;
263         struct ast_frame *f;
264         struct ast_silence_generator *silgen = NULL;
265         struct ast_channel *spyee = NULL;
266         const char *spyer_name;
267
268         ast_channel_lock(chan);
269         spyer_name = ast_strdupa(chan->name);
270         ast_channel_unlock(chan);
271
272         ast_mutex_lock(&spyee_chanspy_ds->lock);
273         if (spyee_chanspy_ds->chan) {
274                 spyee = spyee_chanspy_ds->chan;
275                 ast_channel_lock(spyee);
276         }
277         ast_mutex_unlock(&spyee_chanspy_ds->lock);
278
279         if (!spyee)
280                 return 0;
281
282         /* We now hold the channel lock on spyee */
283
284         if (ast_check_hangup(chan) || ast_check_hangup(spyee)) {
285                 ast_channel_unlock(spyee);
286                 return 0;
287         }
288
289         name = ast_strdupa(spyee->name);
290         ast_verb(2, "Spying on channel %s\n", name);
291
292         memset(&csth, 0, sizeof(csth));
293
294         ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy");
295
296         if (start_spying(spyee, spyer_name, &csth.spy_audiohook)) { /* Unlocks spyee */
297                 ast_audiohook_destroy(&csth.spy_audiohook);
298                 return 0;
299         }
300
301         if (ast_test_flag(flags, OPTION_WHISPER)) {
302                 ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
303                 start_spying(spyee, spyer_name, &csth.whisper_audiohook); /* Unlocks spyee */
304         }
305
306         spyee = NULL;
307
308         csth.volfactor = *volfactor;
309
310         if (csth.volfactor) {
311                 csth.spy_audiohook.options.read_volume = csth.volfactor;
312                 csth.spy_audiohook.options.write_volume = csth.volfactor;
313         }
314
315         csth.fd = fd;
316
317         if (ast_test_flag(flags, OPTION_PRIVATE))
318                 silgen = ast_channel_start_silence_generator(chan);
319         else
320                 ast_activate_generator(chan, &spygen, &csth);
321
322         /* We can no longer rely on 'spyee' being an actual channel;
323            it can be hung up and freed out from under us. However, the
324            channel destructor will put NULL into our csth.spy.chan
325            field when that happens, so that is our signal that the spyee
326            channel has gone away.
327         */
328
329         /* Note: it is very important that the ast_waitfor() be the first
330            condition in this expression, so that if we wait for some period
331            of time before receiving a frame from our spying channel, we check
332            for hangup on the spied-on channel _after_ knowing that a frame
333            has arrived, since the spied-on channel could have gone away while
334            we were waiting
335         */
336         while ((res = ast_waitfor(chan, -1) > -1) && csth.spy_audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
337                 if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
338                         running = -1;
339                         break;
340                 }
341
342                 if (ast_test_flag(flags, OPTION_WHISPER) && f->frametype == AST_FRAME_VOICE) {
343                         ast_audiohook_lock(&csth.whisper_audiohook);
344                         ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
345                         ast_audiohook_unlock(&csth.whisper_audiohook);
346                         ast_frfree(f);
347                         continue;
348                 }
349                 
350                 res = (f->frametype == AST_FRAME_DTMF) ? f->subclass : 0;
351                 ast_frfree(f);
352                 if (!res)
353                         continue;
354
355                 if (x == sizeof(inp))
356                         x = 0;
357
358                 if (res < 0) {
359                         running = -1;
360                         break;
361                 }
362
363                 if (ast_test_flag(flags, OPTION_EXIT)) {
364                         char tmp[2];
365                         tmp[0] = res;
366                         tmp[1] = '\0';
367                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
368                                 ast_debug(1, "Got DTMF %c, goto context %s\n", tmp[0], exitcontext);
369                                 pbx_builtin_setvar_helper(chan, "SPY_CHANNEL", name);
370                                 running = -2;
371                                 break;
372                         } else {
373                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
374                         }
375                 } else if (res >= '0' && res <= '9') {
376                         inp[x++] = res;
377                 }
378
379                 if (res == '*') {
380                         running = 0;
381                         break;
382                 } else if (res == '#') {
383                         if (!ast_strlen_zero(inp)) {
384                                 running = atoi(inp);
385                                 break;
386                         }
387
388                         (*volfactor)++;
389                         if (*volfactor > 4)
390                                 *volfactor = -4;
391                         ast_verb(3, "Setting spy volume on %s to %d\n", chan->name, *volfactor);
392
393                         csth.volfactor = *volfactor;
394                         csth.spy_audiohook.options.read_volume = csth.volfactor;
395                         csth.spy_audiohook.options.write_volume = csth.volfactor;
396                 }
397         }
398
399         if (ast_test_flag(flags, OPTION_PRIVATE))
400                 ast_channel_stop_silence_generator(chan, silgen);
401         else
402                 ast_deactivate_generator(chan);
403
404         if (ast_test_flag(flags, OPTION_WHISPER)) {
405                 ast_audiohook_lock(&csth.whisper_audiohook);
406                 ast_audiohook_detach(&csth.whisper_audiohook);
407                 ast_audiohook_unlock(&csth.whisper_audiohook);
408                 ast_audiohook_destroy(&csth.whisper_audiohook);
409         }
410
411         ast_audiohook_lock(&csth.spy_audiohook);
412         ast_audiohook_detach(&csth.spy_audiohook);
413         ast_audiohook_unlock(&csth.spy_audiohook);
414         ast_audiohook_destroy(&csth.spy_audiohook);
415         
416         ast_verb(2, "Done Spying on channel %s\n", name);
417
418         return running;
419 }
420
421 /*!
422  * \note This relies on the embedded lock to be recursive, as it may be called
423  * due to a call to chanspy_ds_free with the lock held there.
424  */
425 static void chanspy_ds_destroy(void *data)
426 {
427         struct chanspy_ds *chanspy_ds = data;
428
429         /* Setting chan to be NULL is an atomic operation, but we don't want this
430          * value to change while this lock is held.  The lock is held elsewhere
431          * while it performs non-atomic operations with this channel pointer */
432
433         ast_mutex_lock(&chanspy_ds->lock);
434         chanspy_ds->chan = NULL;
435         ast_mutex_unlock(&chanspy_ds->lock);
436 }
437
438 static void chanspy_ds_chan_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
439 {
440         struct chanspy_ds *chanspy_ds = data;
441         
442         ast_mutex_lock(&chanspy_ds->lock);
443         chanspy_ds->chan = new_chan;
444         ast_mutex_unlock(&chanspy_ds->lock);
445 }
446
447 static const struct ast_datastore_info chanspy_ds_info = {
448         .type = "chanspy",
449         .destroy = chanspy_ds_destroy,
450         .chan_fixup = chanspy_ds_chan_fixup,
451 };
452
453 static struct chanspy_ds *chanspy_ds_free(struct chanspy_ds *chanspy_ds)
454 {
455         if (!chanspy_ds)
456                 return NULL;
457
458         ast_mutex_lock(&chanspy_ds->lock);
459         if (chanspy_ds->chan) {
460                 struct ast_datastore *datastore;
461                 struct ast_channel *chan;
462
463                 chan = chanspy_ds->chan;
464
465                 ast_channel_lock(chan);
466                 if ((datastore = ast_channel_datastore_find(chan, &chanspy_ds_info, NULL))) {
467                         ast_channel_datastore_remove(chan, datastore);
468                         /* chanspy_ds->chan is NULL after this call */
469                         chanspy_ds_destroy(datastore->data);
470                         datastore->data = NULL;
471                         ast_channel_datastore_free(datastore);
472                 }
473                 ast_channel_unlock(chan);
474         }
475         ast_mutex_unlock(&chanspy_ds->lock);
476
477         return NULL;
478 }
479
480 /*! \note Returns the channel in the chanspy_ds locked as well as the chanspy_ds locked */
481 static struct chanspy_ds *setup_chanspy_ds(struct ast_channel *chan, struct chanspy_ds *chanspy_ds)
482 {
483         struct ast_datastore *datastore = NULL;
484
485         ast_mutex_lock(&chanspy_ds->lock);
486
487         if (!(datastore = ast_channel_datastore_alloc(&chanspy_ds_info, NULL))) {
488                 ast_mutex_unlock(&chanspy_ds->lock);
489                 chanspy_ds = chanspy_ds_free(chanspy_ds);
490                 ast_channel_unlock(chan);
491                 return NULL;
492         }
493         
494         chanspy_ds->chan = chan;
495         datastore->data = chanspy_ds;
496         ast_channel_datastore_add(chan, datastore);
497
498         return chanspy_ds;
499 }
500
501 static struct chanspy_ds *next_channel(struct ast_channel *chan,
502         const struct ast_channel *last, const char *spec,
503         const char *exten, const char *context, struct chanspy_ds *chanspy_ds)
504 {
505         struct ast_channel *next;
506
507 redo:
508         if (!ast_strlen_zero(spec))
509                 next = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
510         else if (!ast_strlen_zero(exten))
511                 next = ast_walk_channel_by_exten_locked(last, exten, context);
512         else
513                 next = ast_channel_walk_locked(last);
514
515         if (!next)
516                 return NULL;
517
518         if (!strncmp(next->name, "Zap/pseudo", 10)) {
519                 ast_channel_unlock(next);
520                 goto redo;
521         } else if (next == chan) {
522                 last = next;
523                 ast_channel_unlock(next);
524                 goto redo;
525         }
526
527         return setup_chanspy_ds(next, chanspy_ds);
528 }
529
530 static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
531         int volfactor, const int fd, const char *mygroup, const char *myenforced,
532         const char *spec, const char *exten, const char *context)
533 {
534         char nameprefix[AST_NAME_STRLEN];
535         char peer_name[AST_NAME_STRLEN + 5];
536         char exitcontext[AST_MAX_CONTEXT] = "";
537         signed char zero_volume = 0;
538         int waitms;
539         int res;
540         char *ptr;
541         int num;
542         int num_spyed_upon = 1;
543         struct chanspy_ds chanspy_ds;
544
545         if (ast_test_flag(flags, OPTION_EXIT)) {
546                 const char *c;
547                 if ((c = pbx_builtin_getvar_helper(chan, "SPY_EXIT_CONTEXT")))
548                         ast_copy_string(exitcontext, c, sizeof(exitcontext));
549                 else if (!ast_strlen_zero(chan->macrocontext))
550                         ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext));
551                 else
552                         ast_copy_string(exitcontext, chan->context, sizeof(exitcontext));
553         }
554
555         ast_mutex_init(&chanspy_ds.lock);
556
557         if (chan->_state != AST_STATE_UP)
558                 ast_answer(chan);
559
560         ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
561
562         waitms = 100;
563
564         for (;;) {
565                 struct chanspy_ds *peer_chanspy_ds = NULL, *next_chanspy_ds = NULL;
566                 struct ast_channel *prev = NULL, *peer = NULL;
567
568                 if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) {
569                         res = ast_streamfile(chan, "beep", chan->language);
570                         if (!res)
571                                 res = ast_waitstream(chan, "");
572                         else if (res < 0) {
573                                 ast_clear_flag(chan, AST_FLAG_SPYING);
574                                 break;
575                         }
576                         if (!ast_strlen_zero(exitcontext)) {
577                                 char tmp[2];
578                                 tmp[0] = res;
579                                 tmp[1] = '\0';
580                                 if (!ast_goto_if_exists(chan, exitcontext, tmp, 1))
581                                         goto exit;
582                                 else
583                                         ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
584                         }
585                 }
586
587                 res = ast_waitfordigit(chan, waitms);
588                 if (res < 0) {
589                         ast_clear_flag(chan, AST_FLAG_SPYING);
590                         break;
591                 }
592                 if (!ast_strlen_zero(exitcontext)) {
593                         char tmp[2];
594                         tmp[0] = res;
595                         tmp[1] = '\0';
596                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1))
597                                 goto exit;
598                         else
599                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
600                 }
601
602                 /* reset for the next loop around, unless overridden later */
603                 waitms = 100;
604                 num_spyed_upon = 0;
605
606                 for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds);
607                      peer_chanspy_ds;
608                          chanspy_ds_free(peer_chanspy_ds), prev = peer,
609                      peer_chanspy_ds = next_chanspy_ds ? next_chanspy_ds : 
610                                 next_channel(chan, prev, spec, exten, context, &chanspy_ds), next_chanspy_ds = NULL) {
611                         const char *group;
612                         int igrp = !mygroup;
613                         char *groups[25];
614                         int num_groups = 0;
615                         char *dup_group;
616                         int x;
617                         char *s;
618                         char *buffer;
619                         char *end;
620                         char *ext;
621                         char *form_enforced;
622                         int ienf = !myenforced;
623                         struct ast_channel *peer;
624
625                         peer = peer_chanspy_ds->chan;
626
627                         ast_mutex_unlock(&peer_chanspy_ds->lock);
628
629                         if (peer == prev) {
630                                 ast_channel_unlock(peer);
631                                 chanspy_ds_free(peer_chanspy_ds);
632                                 break;
633                         }
634
635                         if (ast_check_hangup(chan)) {
636                                 ast_channel_unlock(peer);
637                                 chanspy_ds_free(peer_chanspy_ds);
638                                 break;
639                         }
640
641                         if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(peer)) {
642                                 ast_channel_unlock(peer);
643                                 continue;
644                         }
645
646                         if (ast_check_hangup(peer) || ast_test_flag(peer, AST_FLAG_SPYING)) {
647                                 ast_channel_unlock(peer);
648                                 continue;
649                         }
650
651                         if (mygroup) {
652                                 if ((group = pbx_builtin_getvar_helper(peer, "SPYGROUP"))) {
653                                         dup_group = ast_strdupa(group);
654                                         num_groups = ast_app_separate_args(dup_group, ':', groups,
655                                                 sizeof(groups) / sizeof(groups[0]));
656                                 }
657
658                                 for (x = 0; x < num_groups; x++) {
659                                         if (!strcmp(mygroup, groups[x])) {
660                                                 igrp = 1;
661                                                 break;
662                                         }
663                                 }
664                         }
665
666                         if (!igrp) {
667                                 ast_channel_unlock(peer);
668                                 continue;
669                         }
670
671                         if (myenforced) {
672
673                                 /* We don't need to allocate more space than just the
674                                 length of (peer->name) for ext as we will cut the
675                                 channel name's ending before copying into ext */
676
677                                 ext = alloca(strlen(peer->name));
678
679                                 form_enforced = alloca(strlen(myenforced) + 3);
680
681                                 strcpy(form_enforced, ":");
682                                 strcat(form_enforced, myenforced);
683                                 strcat(form_enforced, ":");
684
685                                 buffer = ast_strdupa(peer->name);
686                                 
687                                 if ((end = strchr(buffer, '-'))) {
688                                         *end++ = ':';
689                                         *end = '\0';
690                                 }
691
692                                 strcpy(ext, ":");
693                                 strcat(ext, buffer);
694
695                                 if (strcasestr(form_enforced, ext))
696                                         ienf = 1;
697                         }
698
699                         if (!ienf)
700                                 continue;
701
702                         strcpy(peer_name, "spy-");
703                         strncat(peer_name, peer->name, AST_NAME_STRLEN - 4 - 1);
704                         ptr = strchr(peer_name, '/');
705                         *ptr++ = '\0';
706
707                         for (s = peer_name; s < ptr; s++)
708                                 *s = tolower(*s);
709                 
710                         /* We have to unlock the peer channel here to avoid a deadlock.
711                          * So, when we need it again, we have to lock the datastore and get
712                          * the pointer from there to see if the channel is still valid. */
713                         ast_channel_unlock(peer);
714                         peer = NULL;
715
716                         if (!ast_test_flag(flags, OPTION_QUIET)) {
717                                 if (!ast_test_flag(flags, OPTION_NOTECH)) {
718                                         if (ast_fileexists(peer_name, NULL, NULL) != -1) {
719                                                 res = ast_streamfile(chan, peer_name, chan->language);
720                                                 if (!res) {
721                                                         res = ast_waitstream(chan, "");
722                                                 }
723                                                 if (res) {
724                                                         chanspy_ds_free(peer_chanspy_ds);
725                                                         break;
726                                                 }
727                                         } else {
728                                                 res = ast_say_character_str(chan, peer_name, "", chan->language);
729                                         }
730                                 }
731                                 if ((num = atoi(ptr)))
732                                         ast_say_digits(chan, atoi(ptr), "", chan->language);
733                         }
734
735                         waitms = 5000;
736                         res = channel_spy(chan, peer_chanspy_ds, &volfactor, fd, flags, exitcontext);
737                         num_spyed_upon++;       
738
739                         if (res == -1) {
740                                 chanspy_ds_free(peer_chanspy_ds);
741                                 goto exit;
742                         } else if (res == -2) {
743                                 res = 0;
744                                 chanspy_ds_free(peer_chanspy_ds);
745                                 goto exit;
746                         } else if (res > 1 && spec) {
747                                 struct ast_channel *next;
748
749                                 snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);
750
751                                 if ((next = ast_get_channel_by_name_prefix_locked(nameprefix, strlen(nameprefix)))) {
752                                         peer_chanspy_ds = chanspy_ds_free(peer_chanspy_ds);
753                                         next_chanspy_ds = setup_chanspy_ds(next, &chanspy_ds);
754                                 } else {
755                                         /* stay on this channel, if it is still valid */
756
757                                         ast_mutex_lock(&peer_chanspy_ds->lock);
758                                         if (peer_chanspy_ds->chan) {
759                                                 ast_channel_lock(peer_chanspy_ds->chan);
760                                                 next_chanspy_ds = peer_chanspy_ds;
761                                                 peer_chanspy_ds = NULL;
762                                         } else {
763                                                 /* the channel is gone */
764                                                 ast_mutex_unlock(&peer_chanspy_ds->lock);
765                                                 next_chanspy_ds = NULL;
766                                         }
767                                 }
768
769                                 peer = NULL;
770                         }
771                 }
772                 if (res == -1 || ast_check_hangup(chan))
773                         break;
774         }
775 exit:
776
777         ast_clear_flag(chan, AST_FLAG_SPYING);
778
779         ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
780
781         ast_mutex_destroy(&chanspy_ds.lock);
782
783         return res;
784 }
785
786 static int chanspy_exec(struct ast_channel *chan, void *data)
787 {
788         char *myenforced = NULL;
789         char *mygroup = NULL;
790         char *recbase = NULL;
791         int fd = 0;
792         struct ast_flags flags;
793         int oldwf = 0;
794         int volfactor = 0;
795         int res;
796         AST_DECLARE_APP_ARGS(args,
797                 AST_APP_ARG(spec);
798                 AST_APP_ARG(options);
799         );
800         char *opts[OPT_ARG_ARRAY_SIZE];
801
802         data = ast_strdupa(data);
803         AST_STANDARD_APP_ARGS(args, data);
804
805         if (args.spec && !strcmp(args.spec, "all"))
806                 args.spec = NULL;
807
808         if (args.options) {
809                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
810                 if (ast_test_flag(&flags, OPTION_GROUP))
811                         mygroup = opts[OPT_ARG_GROUP];
812
813                 if (ast_test_flag(&flags, OPTION_RECORD) &&
814                         !(recbase = opts[OPT_ARG_RECORD]))
815                         recbase = "chanspy";
816
817                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
818                         int vol;
819
820                         if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
821                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
822                         else
823                                 volfactor = vol;
824                 }
825
826                 if (ast_test_flag(&flags, OPTION_PRIVATE))
827                         ast_set_flag(&flags, OPTION_WHISPER);
828
829                 if (ast_test_flag(&flags, OPTION_ENFORCED))
830                         myenforced = opts[OPT_ARG_ENFORCED];
831
832         } else
833                 ast_clear_flag(&flags, AST_FLAGS_ALL);
834
835         oldwf = chan->writeformat;
836         if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
837                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
838                 return -1;
839         }
840
841         if (recbase) {
842                 char filename[PATH_MAX];
843
844                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
845                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
846                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
847                         fd = 0;
848                 }
849         }
850
851         res = common_exec(chan, &flags, volfactor, fd, mygroup, myenforced, args.spec, NULL, NULL);
852
853         if (fd)
854                 close(fd);
855
856         if (oldwf && ast_set_write_format(chan, oldwf) < 0)
857                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
858
859         return res;
860 }
861
862 static int extenspy_exec(struct ast_channel *chan, void *data)
863 {
864         char *ptr, *exten = NULL;
865         char *mygroup = NULL;
866         char *recbase = NULL;
867         int fd = 0;
868         struct ast_flags flags;
869         int oldwf = 0;
870         int volfactor = 0;
871         int res;
872         AST_DECLARE_APP_ARGS(args,
873                 AST_APP_ARG(context);
874                 AST_APP_ARG(options);
875         );
876
877         data = ast_strdupa(data);
878
879         AST_STANDARD_APP_ARGS(args, data);
880         if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
881                 exten = args.context;
882                 *ptr++ = '\0';
883                 args.context = ptr;
884         }
885
886         if (ast_strlen_zero(args.context))
887                 args.context = ast_strdupa(chan->context);
888
889         if (args.options) {
890                 char *opts[OPT_ARG_ARRAY_SIZE];
891
892                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
893                 if (ast_test_flag(&flags, OPTION_GROUP))
894                         mygroup = opts[OPT_ARG_GROUP];
895
896                 if (ast_test_flag(&flags, OPTION_RECORD) &&
897                         !(recbase = opts[OPT_ARG_RECORD]))
898                         recbase = "chanspy";
899
900                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
901                         int vol;
902
903                         if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
904                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
905                         else
906                                 volfactor = vol;
907                 }
908
909                 if (ast_test_flag(&flags, OPTION_PRIVATE))
910                         ast_set_flag(&flags, OPTION_WHISPER);
911         } else
912                 ast_clear_flag(&flags, AST_FLAGS_ALL);
913
914         oldwf = chan->writeformat;
915         if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
916                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
917                 return -1;
918         }
919
920         if (recbase) {
921                 char filename[PATH_MAX];
922
923                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
924                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
925                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
926                         fd = 0;
927                 }
928         }
929
930
931         res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, exten, args.context);
932
933         if (fd)
934                 close(fd);
935
936         if (oldwf && ast_set_write_format(chan, oldwf) < 0)
937                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
938
939         return res;
940 }
941
942 static int unload_module(void)
943 {
944         int res = 0;
945
946         res |= ast_unregister_application(app_chan);
947         res |= ast_unregister_application(app_ext);
948
949         return res;
950 }
951
952 static int load_module(void)
953 {
954         int res = 0;
955
956         res |= ast_register_application(app_chan, chanspy_exec, tdesc, desc_chan);
957         res |= ast_register_application(app_ext, extenspy_exec, tdesc, desc_ext);
958
959         return res;
960 }
961
962 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Listen to the audio of an active channel");