8450c927e9d96f772b619ab48e374b782f250eaf
[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_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
244         }
245         return res;
246 }
247
248 struct chanspy_ds {
249         struct ast_channel *chan;
250         ast_mutex_t lock;
251 };
252
253 static int channel_spy(struct ast_channel *chan, struct chanspy_ds *spyee_chanspy_ds, 
254         int *volfactor, int fd, const struct ast_flags *flags, char *exitcontext) 
255 {
256         struct chanspy_translation_helper csth;
257         int running = 0, res, x = 0;
258         char inp[24] = {0};
259         char *name;
260         struct ast_frame *f;
261         struct ast_silence_generator *silgen = NULL;
262         struct ast_channel *spyee = NULL;
263         const char *spyer_name;
264
265         ast_channel_lock(chan);
266         spyer_name = ast_strdupa(chan->name);
267         ast_channel_unlock(chan);
268
269         ast_mutex_lock(&spyee_chanspy_ds->lock);
270         if (spyee_chanspy_ds->chan) {
271                 spyee = spyee_chanspy_ds->chan;
272                 ast_channel_lock(spyee);
273         }
274         ast_mutex_unlock(&spyee_chanspy_ds->lock);
275
276         if (!spyee)
277                 return 0;
278
279         /* We now hold the channel lock on spyee */
280
281         if (ast_check_hangup(chan) || ast_check_hangup(spyee)) {
282                 ast_channel_unlock(spyee);
283                 return 0;
284         }
285
286         name = ast_strdupa(spyee->name);
287         ast_verb(2, "Spying on channel %s\n", name);
288
289         memset(&csth, 0, sizeof(csth));
290
291         ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy");
292
293         if (start_spying(spyee, spyer_name, &csth.spy_audiohook)) {
294                 ast_audiohook_destroy(&csth.spy_audiohook);
295                 ast_channel_unlock(spyee);
296                 return 0;
297         }
298
299         if (ast_test_flag(flags, OPTION_WHISPER)) {
300                 ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
301                 start_spying(spyee, spyer_name, &csth.whisper_audiohook);
302         }
303
304         ast_channel_unlock(spyee);
305         spyee = NULL;
306
307         csth.volfactor = *volfactor;
308
309         if (csth.volfactor) {
310                 csth.spy_audiohook.options.read_volume = csth.volfactor;
311                 csth.spy_audiohook.options.write_volume = csth.volfactor;
312         }
313
314         csth.fd = fd;
315
316         if (ast_test_flag(flags, OPTION_PRIVATE))
317                 silgen = ast_channel_start_silence_generator(chan);
318         else
319                 ast_activate_generator(chan, &spygen, &csth);
320
321         /* We can no longer rely on 'spyee' being an actual channel;
322            it can be hung up and freed out from under us. However, the
323            channel destructor will put NULL into our csth.spy.chan
324            field when that happens, so that is our signal that the spyee
325            channel has gone away.
326         */
327
328         /* Note: it is very important that the ast_waitfor() be the first
329            condition in this expression, so that if we wait for some period
330            of time before receiving a frame from our spying channel, we check
331            for hangup on the spied-on channel _after_ knowing that a frame
332            has arrived, since the spied-on channel could have gone away while
333            we were waiting
334         */
335         while ((res = ast_waitfor(chan, -1) > -1) && csth.spy_audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
336                 if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
337                         running = -1;
338                         break;
339                 }
340
341                 if (ast_test_flag(flags, OPTION_WHISPER) && f->frametype == AST_FRAME_VOICE) {
342                         ast_audiohook_lock(&csth.whisper_audiohook);
343                         ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
344                         ast_audiohook_unlock(&csth.whisper_audiohook);
345                         ast_frfree(f);
346                         continue;
347                 }
348                 
349                 res = (f->frametype == AST_FRAME_DTMF) ? f->subclass : 0;
350                 ast_frfree(f);
351                 if (!res)
352                         continue;
353
354                 if (x == sizeof(inp))
355                         x = 0;
356
357                 if (res < 0) {
358                         running = -1;
359                         break;
360                 }
361
362                 if (ast_test_flag(flags, OPTION_EXIT)) {
363                         char tmp[2];
364                         tmp[0] = res;
365                         tmp[1] = '\0';
366                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
367                                 ast_debug(1, "Got DTMF %c, goto context %s\n", tmp[0], exitcontext);
368                                 pbx_builtin_setvar_helper(chan, "SPY_CHANNEL", name);
369                                 running = -2;
370                                 break;
371                         } else {
372                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
373                         }
374                 } else if (res >= '0' && res <= '9') {
375                         inp[x++] = res;
376                 }
377
378                 if (res == '*') {
379                         running = 0;
380                         break;
381                 } else if (res == '#') {
382                         if (!ast_strlen_zero(inp)) {
383                                 running = atoi(inp);
384                                 break;
385                         }
386
387                         (*volfactor)++;
388                         if (*volfactor > 4)
389                                 *volfactor = -4;
390                         ast_verb(3, "Setting spy volume on %s to %d\n", chan->name, *volfactor);
391
392                         csth.volfactor = *volfactor;
393                         csth.spy_audiohook.options.read_volume = csth.volfactor;
394                         csth.spy_audiohook.options.write_volume = csth.volfactor;
395                 }
396         }
397
398         if (ast_test_flag(flags, OPTION_PRIVATE))
399                 ast_channel_stop_silence_generator(chan, silgen);
400         else
401                 ast_deactivate_generator(chan);
402
403         if (ast_test_flag(flags, OPTION_WHISPER)) {
404                 ast_audiohook_lock(&csth.whisper_audiohook);
405                 ast_audiohook_detach(&csth.whisper_audiohook);
406                 ast_audiohook_unlock(&csth.whisper_audiohook);
407                 ast_audiohook_destroy(&csth.whisper_audiohook);
408         }
409
410         ast_audiohook_lock(&csth.spy_audiohook);
411         ast_audiohook_detach(&csth.spy_audiohook);
412         ast_audiohook_unlock(&csth.spy_audiohook);
413         ast_audiohook_destroy(&csth.spy_audiohook);
414         
415         ast_verb(2, "Done Spying on channel %s\n", name);
416
417         return running;
418 }
419
420 /*!
421  * \note This relies on the embedded lock to be recursive, as it may be called
422  * due to a call to chanspy_ds_free with the lock held there.
423  */
424 static void chanspy_ds_destroy(void *data)
425 {
426         struct chanspy_ds *chanspy_ds = data;
427
428         /* Setting chan to be NULL is an atomic operation, but we don't want this
429          * value to change while this lock is held.  The lock is held elsewhere
430          * while it performs non-atomic operations with this channel pointer */
431
432         ast_mutex_lock(&chanspy_ds->lock);
433         chanspy_ds->chan = NULL;
434         ast_mutex_unlock(&chanspy_ds->lock);
435 }
436
437 static void chanspy_ds_chan_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
438 {
439         struct chanspy_ds *chanspy_ds = data;
440         
441         ast_mutex_lock(&chanspy_ds->lock);
442         chanspy_ds->chan = new_chan;
443         ast_mutex_unlock(&chanspy_ds->lock);
444 }
445
446 static const struct ast_datastore_info chanspy_ds_info = {
447         .type = "chanspy",
448         .destroy = chanspy_ds_destroy,
449         .chan_fixup = chanspy_ds_chan_fixup,
450 };
451
452 static struct chanspy_ds *chanspy_ds_free(struct chanspy_ds *chanspy_ds)
453 {
454         if (!chanspy_ds)
455                 return NULL;
456
457         ast_mutex_lock(&chanspy_ds->lock);
458         if (chanspy_ds->chan) {
459                 struct ast_datastore *datastore;
460                 struct ast_channel *chan;
461
462                 chan = chanspy_ds->chan;
463
464                 ast_channel_lock(chan);
465                 if ((datastore = ast_channel_datastore_find(chan, &chanspy_ds_info, NULL))) {
466                         ast_channel_datastore_remove(chan, datastore);
467                         /* chanspy_ds->chan is NULL after this call */
468                         chanspy_ds_destroy(datastore->data);
469                         datastore->data = NULL;
470                         ast_channel_datastore_free(datastore);
471                 }
472                 ast_channel_unlock(chan);
473         }
474         ast_mutex_unlock(&chanspy_ds->lock);
475
476         return NULL;
477 }
478
479 /*! \note Returns the channel in the chanspy_ds locked as well as the chanspy_ds locked */
480 static struct chanspy_ds *setup_chanspy_ds(struct ast_channel *chan, struct chanspy_ds *chanspy_ds)
481 {
482         struct ast_datastore *datastore = NULL;
483
484         ast_mutex_lock(&chanspy_ds->lock);
485
486         if (!(datastore = ast_channel_datastore_alloc(&chanspy_ds_info, NULL))) {
487                 ast_mutex_unlock(&chanspy_ds->lock);
488                 chanspy_ds = chanspy_ds_free(chanspy_ds);
489                 ast_channel_unlock(chan);
490                 return NULL;
491         }
492         
493         chanspy_ds->chan = chan;
494         datastore->data = chanspy_ds;
495         ast_channel_datastore_add(chan, datastore);
496
497         return chanspy_ds;
498 }
499
500 static struct chanspy_ds *next_channel(struct ast_channel *chan,
501         const struct ast_channel *last, const char *spec,
502         const char *exten, const char *context, struct chanspy_ds *chanspy_ds)
503 {
504         struct ast_channel *next;
505
506 redo:
507         if (!ast_strlen_zero(spec))
508                 next = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
509         else if (!ast_strlen_zero(exten))
510                 next = ast_walk_channel_by_exten_locked(last, exten, context);
511         else
512                 next = ast_channel_walk_locked(last);
513
514         if (!next)
515                 return NULL;
516
517         if (!strncmp(next->name, "Zap/pseudo", 10)) {
518                 ast_channel_unlock(next);
519                 goto redo;
520         } else if (next == chan) {
521                 last = next;
522                 ast_channel_unlock(next);
523                 goto redo;
524         }
525
526         return setup_chanspy_ds(next, chanspy_ds);
527 }
528
529 static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
530         int volfactor, const int fd, const char *mygroup, const char *myenforced,
531         const char *spec, const char *exten, const char *context)
532 {
533         char nameprefix[AST_NAME_STRLEN];
534         char peer_name[AST_NAME_STRLEN + 5];
535         char exitcontext[AST_MAX_CONTEXT] = "";
536         signed char zero_volume = 0;
537         int waitms;
538         int res;
539         char *ptr;
540         int num;
541         int num_spyed_upon = 1;
542         struct chanspy_ds chanspy_ds;
543
544         if (ast_test_flag(flags, OPTION_EXIT)) {
545                 const char *c;
546                 if ((c = pbx_builtin_getvar_helper(chan, "SPY_EXIT_CONTEXT")))
547                         ast_copy_string(exitcontext, c, sizeof(exitcontext));
548                 else if (!ast_strlen_zero(chan->macrocontext))
549                         ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext));
550                 else
551                         ast_copy_string(exitcontext, chan->context, sizeof(exitcontext));
552         }
553
554         ast_mutex_init(&chanspy_ds.lock);
555
556         if (chan->_state != AST_STATE_UP)
557                 ast_answer(chan);
558
559         ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
560
561         waitms = 100;
562
563         for (;;) {
564                 struct chanspy_ds *peer_chanspy_ds = NULL, *next_chanspy_ds = NULL;
565                 struct ast_channel *prev = NULL, *peer = NULL;
566
567                 if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) {
568                         res = ast_streamfile(chan, "beep", chan->language);
569                         if (!res)
570                                 res = ast_waitstream(chan, "");
571                         else if (res < 0) {
572                                 ast_clear_flag(chan, AST_FLAG_SPYING);
573                                 break;
574                         }
575                         if (!ast_strlen_zero(exitcontext)) {
576                                 char tmp[2];
577                                 tmp[0] = res;
578                                 tmp[1] = '\0';
579                                 if (!ast_goto_if_exists(chan, exitcontext, tmp, 1))
580                                         goto exit;
581                                 else
582                                         ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
583                         }
584                 }
585
586                 res = ast_waitfordigit(chan, waitms);
587                 if (res < 0) {
588                         ast_clear_flag(chan, AST_FLAG_SPYING);
589                         break;
590                 }
591                 if (!ast_strlen_zero(exitcontext)) {
592                         char tmp[2];
593                         tmp[0] = res;
594                         tmp[1] = '\0';
595                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1))
596                                 goto exit;
597                         else
598                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
599                 }
600
601                 /* reset for the next loop around, unless overridden later */
602                 waitms = 100;
603                 num_spyed_upon = 0;
604
605                 for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds);
606                      peer_chanspy_ds;
607                          chanspy_ds_free(peer_chanspy_ds), prev = peer,
608                      peer_chanspy_ds = next_chanspy_ds ? next_chanspy_ds : 
609                                 next_channel(chan, prev, spec, exten, context, &chanspy_ds), next_chanspy_ds = NULL) {
610                         const char *group;
611                         int igrp = !mygroup;
612                         char *groups[25];
613                         int num_groups = 0;
614                         char *dup_group;
615                         int x;
616                         char *s;
617                         char *buffer;
618                         char *end;
619                         char *ext;
620                         char *form_enforced;
621                         int ienf = !myenforced;
622
623                         peer = peer_chanspy_ds->chan;
624
625                         ast_mutex_unlock(&peer_chanspy_ds->lock);
626
627                         if (peer == prev) {
628                                 ast_channel_unlock(peer);
629                                 chanspy_ds_free(peer_chanspy_ds);
630                                 break;
631                         }
632
633                         if (ast_check_hangup(chan)) {
634                                 ast_channel_unlock(peer);
635                                 chanspy_ds_free(peer_chanspy_ds);
636                                 break;
637                         }
638
639                         if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(peer)) {
640                                 ast_channel_unlock(peer);
641                                 continue;
642                         }
643
644                         if (ast_check_hangup(peer) || ast_test_flag(peer, AST_FLAG_SPYING)) {
645                                 ast_channel_unlock(peer);
646                                 continue;
647                         }
648
649                         if (mygroup) {
650                                 if ((group = pbx_builtin_getvar_helper(peer, "SPYGROUP"))) {
651                                         dup_group = ast_strdupa(group);
652                                         num_groups = ast_app_separate_args(dup_group, ':', groups,
653                                                 sizeof(groups) / sizeof(groups[0]));
654                                 }
655
656                                 for (x = 0; x < num_groups; x++) {
657                                         if (!strcmp(mygroup, groups[x])) {
658                                                 igrp = 1;
659                                                 break;
660                                         }
661                                 }
662                         }
663
664                         if (!igrp) {
665                                 ast_channel_unlock(peer);
666                                 continue;
667                         }
668
669                         if (myenforced) {
670
671                                 /* We don't need to allocate more space than just the
672                                 length of (peer->name) for ext as we will cut the
673                                 channel name's ending before copying into ext */
674
675                                 ext = alloca(strlen(peer->name));
676
677                                 form_enforced = alloca(strlen(myenforced) + 3);
678
679                                 strcpy(form_enforced, ":");
680                                 strcat(form_enforced, myenforced);
681                                 strcat(form_enforced, ":");
682
683                                 buffer = ast_strdupa(peer->name);
684                                 
685                                 if ((end = strchr(buffer, '-'))) {
686                                         *end++ = ':';
687                                         *end = '\0';
688                                 }
689
690                                 strcpy(ext, ":");
691                                 strcat(ext, buffer);
692
693                                 if (strcasestr(form_enforced, ext))
694                                         ienf = 1;
695                         }
696
697                         if (!ienf)
698                                 continue;
699
700                         strcpy(peer_name, "spy-");
701                         strncat(peer_name, peer->name, AST_NAME_STRLEN - 4 - 1);
702                         ptr = strchr(peer_name, '/');
703                         *ptr++ = '\0';
704
705                         for (s = peer_name; s < ptr; s++)
706                                 *s = tolower(*s);
707                         /* We have to unlock the peer channel here to avoid a deadlock.
708                          * So, when we need to dereference it again, we have to lock the 
709                          * datastore and get the pointer from there to see if the channel 
710                          * is still valid. */
711                         ast_channel_unlock(peer);
712
713                         if (!ast_test_flag(flags, OPTION_QUIET)) {
714                                 if (!ast_test_flag(flags, OPTION_NOTECH)) {
715                                         if (ast_fileexists(peer_name, NULL, NULL) != -1) {
716                                                 res = ast_streamfile(chan, peer_name, chan->language);
717                                                 if (!res) {
718                                                         res = ast_waitstream(chan, "");
719                                                 }
720                                                 if (res) {
721                                                         chanspy_ds_free(peer_chanspy_ds);
722                                                         break;
723                                                 }
724                                         } else {
725                                                 res = ast_say_character_str(chan, peer_name, "", chan->language);
726                                         }
727                                 }
728                                 if ((num = atoi(ptr)))
729                                         ast_say_digits(chan, atoi(ptr), "", chan->language);
730                         }
731
732                         res = channel_spy(chan, peer_chanspy_ds, &volfactor, fd, flags, exitcontext);
733                         num_spyed_upon++;       
734
735                         if (res == -1) {
736                                 chanspy_ds_free(peer_chanspy_ds);
737                                 goto exit;
738                         } else if (res == -2) {
739                                 res = 0;
740                                 chanspy_ds_free(peer_chanspy_ds);
741                                 goto exit;
742                         } else if (res > 1 && spec) {
743                                 struct ast_channel *next;
744
745                                 snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);
746
747                                 if ((next = ast_get_channel_by_name_prefix_locked(nameprefix, strlen(nameprefix)))) {
748                                         peer_chanspy_ds = chanspy_ds_free(peer_chanspy_ds);
749                                         next_chanspy_ds = setup_chanspy_ds(next, &chanspy_ds);
750                                 } else {
751                                         /* stay on this channel, if it is still valid */
752
753                                         ast_mutex_lock(&peer_chanspy_ds->lock);
754                                         if (peer_chanspy_ds->chan) {
755                                                 ast_channel_lock(peer_chanspy_ds->chan);
756                                                 next_chanspy_ds = peer_chanspy_ds;
757                                                 peer_chanspy_ds = NULL;
758                                         } else {
759                                                 /* the channel is gone */
760                                                 ast_mutex_unlock(&peer_chanspy_ds->lock);
761                                                 next_chanspy_ds = NULL;
762                                         }
763                                 }
764
765                                 peer = NULL;
766                         }
767                 }
768                 if (res == -1 || ast_check_hangup(chan))
769                         break;
770         }
771 exit:
772
773         ast_clear_flag(chan, AST_FLAG_SPYING);
774
775         ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
776
777         ast_mutex_destroy(&chanspy_ds.lock);
778
779         return res;
780 }
781
782 static int chanspy_exec(struct ast_channel *chan, void *data)
783 {
784         char *myenforced = NULL;
785         char *mygroup = NULL;
786         char *recbase = NULL;
787         int fd = 0;
788         struct ast_flags flags;
789         int oldwf = 0;
790         int volfactor = 0;
791         int res;
792         AST_DECLARE_APP_ARGS(args,
793                 AST_APP_ARG(spec);
794                 AST_APP_ARG(options);
795         );
796         char *opts[OPT_ARG_ARRAY_SIZE];
797
798         data = ast_strdupa(data);
799         AST_STANDARD_APP_ARGS(args, data);
800
801         if (args.spec && !strcmp(args.spec, "all"))
802                 args.spec = NULL;
803
804         if (args.options) {
805                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
806                 if (ast_test_flag(&flags, OPTION_GROUP))
807                         mygroup = opts[OPT_ARG_GROUP];
808
809                 if (ast_test_flag(&flags, OPTION_RECORD) &&
810                         !(recbase = opts[OPT_ARG_RECORD]))
811                         recbase = "chanspy";
812
813                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
814                         int vol;
815
816                         if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
817                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
818                         else
819                                 volfactor = vol;
820                 }
821
822                 if (ast_test_flag(&flags, OPTION_PRIVATE))
823                         ast_set_flag(&flags, OPTION_WHISPER);
824
825                 if (ast_test_flag(&flags, OPTION_ENFORCED))
826                         myenforced = opts[OPT_ARG_ENFORCED];
827
828         } else
829                 ast_clear_flag(&flags, AST_FLAGS_ALL);
830
831         oldwf = chan->writeformat;
832         if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
833                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
834                 return -1;
835         }
836
837         if (recbase) {
838                 char filename[PATH_MAX];
839
840                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
841                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
842                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
843                         fd = 0;
844                 }
845         }
846
847         res = common_exec(chan, &flags, volfactor, fd, mygroup, myenforced, args.spec, NULL, NULL);
848
849         if (fd)
850                 close(fd);
851
852         if (oldwf && ast_set_write_format(chan, oldwf) < 0)
853                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
854
855         return res;
856 }
857
858 static int extenspy_exec(struct ast_channel *chan, void *data)
859 {
860         char *ptr, *exten = NULL;
861         char *mygroup = NULL;
862         char *recbase = NULL;
863         int fd = 0;
864         struct ast_flags flags;
865         int oldwf = 0;
866         int volfactor = 0;
867         int res;
868         AST_DECLARE_APP_ARGS(args,
869                 AST_APP_ARG(context);
870                 AST_APP_ARG(options);
871         );
872
873         data = ast_strdupa(data);
874
875         AST_STANDARD_APP_ARGS(args, data);
876         if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
877                 exten = args.context;
878                 *ptr++ = '\0';
879                 args.context = ptr;
880         }
881
882         if (ast_strlen_zero(args.context))
883                 args.context = ast_strdupa(chan->context);
884
885         if (args.options) {
886                 char *opts[OPT_ARG_ARRAY_SIZE];
887
888                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
889                 if (ast_test_flag(&flags, OPTION_GROUP))
890                         mygroup = opts[OPT_ARG_GROUP];
891
892                 if (ast_test_flag(&flags, OPTION_RECORD) &&
893                         !(recbase = opts[OPT_ARG_RECORD]))
894                         recbase = "chanspy";
895
896                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
897                         int vol;
898
899                         if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
900                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
901                         else
902                                 volfactor = vol;
903                 }
904
905                 if (ast_test_flag(&flags, OPTION_PRIVATE))
906                         ast_set_flag(&flags, OPTION_WHISPER);
907         } else
908                 ast_clear_flag(&flags, AST_FLAGS_ALL);
909
910         oldwf = chan->writeformat;
911         if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
912                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
913                 return -1;
914         }
915
916         if (recbase) {
917                 char filename[PATH_MAX];
918
919                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
920                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
921                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
922                         fd = 0;
923                 }
924         }
925
926
927         res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, exten, args.context);
928
929         if (fd)
930                 close(fd);
931
932         if (oldwf && ast_set_write_format(chan, oldwf) < 0)
933                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
934
935         return res;
936 }
937
938 static int unload_module(void)
939 {
940         int res = 0;
941
942         res |= ast_unregister_application(app_chan);
943         res |= ast_unregister_application(app_ext);
944
945         return res;
946 }
947
948 static int load_module(void)
949 {
950         int res = 0;
951
952         res |= ast_register_application(app_chan, chanspy_exec, tdesc, desc_chan);
953         res |= ast_register_application(app_ext, extenspy_exec, tdesc, desc_ext);
954
955         return res;
956 }
957
958 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Listen to the audio of an active channel");