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