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