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