2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2005 Anthony Minessale II (anthmct@yahoo.com)
5 * Copyright (C) 2005 - 2006, Digium, Inc.
7 * A license has been granted to Digium (via disclaimer) for the use of
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.
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.
23 * \brief ChanSpy: Listen in on any channel.
25 * \author Anthony Minessale II <anthmct@yahoo.com>
27 * \ingroup applications
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40 #include "asterisk/file.h"
41 #include "asterisk/logger.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/chanspy.h"
44 #include "asterisk/features.h"
45 #include "asterisk/options.h"
46 #include "asterisk/app.h"
47 #include "asterisk/utils.h"
48 #include "asterisk/say.h"
49 #include "asterisk/pbx.h"
50 #include "asterisk/translate.h"
51 #include "asterisk/module.h"
52 #include "asterisk/lock.h"
54 #define AST_NAME_STRLEN 256
56 static const char *tdesc = "Listen to a channel, and optionally whisper into it";
57 static const char *app_chan = "ChanSpy";
58 static const char *desc_chan =
59 " ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
60 "audio from an Asterisk channel. This includes the audio coming in and\n"
61 "out of the channel being spied on. If the 'chanprefix' parameter is specified,\n"
62 "only channels beginning with this string will be spied upon.\n"
63 " While spying, the following actions may be performed:\n"
64 " - Dialing # cycles the volume level.\n"
65 " - Dialing * will stop spying and look for another channel to spy on.\n"
66 " - Dialing a series of digits followed by # builds a channel name to append\n"
67 " to 'chanprefix'. For example, executing ChanSpy(Agent) and then dialing\n"
68 " the digits '1234#' while spying will begin spying on the channel\n"
71 " b - Only spy on channels involved in a bridged call.\n"
72 " g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n"
73 " contain 'grp' in an optional : delimited list.\n"
74 " q - Don't play a beep when beginning to spy on a channel, or speak the\n"
75 " selected channel name.\n"
76 " r[(basename)] - Record the session to the monitor spool directory. An\n"
77 " optional base for the filename may be specified. The\n"
78 " default is 'chanspy'.\n"
79 " v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
80 " negative value refers to a quieter setting.\n"
81 " w - Enable 'whisper' mode, so the spying channel can talk to\n"
82 " the spied-on channel.\n"
83 " W - Enable 'private whisper' mode, so the spying channel can\n"
84 " talk to the spied-on channel but cannot listen to that\n"
88 static const char *app_ext = "ExtenSpy";
89 static const char *desc_ext =
90 " ExtenSpy(exten[@context][|options]): This application is used to listen to the\n"
91 "audio from an Asterisk channel. This includes the audio coming in and\n"
92 "out of the channel being spied on. Only channels created by outgoing calls for the\n"
93 "specified extension will be selected for spying. If the optional context is not\n"
94 "supplied, the current channel's context will be used.\n"
95 " While spying, the following actions may be performed:\n"
96 " - Dialing # cycles the volume level.\n"
97 " - Dialing * will stop spying and look for another channel to spy on.\n"
99 " b - Only spy on channels involved in a bridged call.\n"
100 " g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n"
101 " contain 'grp' in an optional : delimited list.\n"
102 " q - Don't play a beep when beginning to spy on a channel, or speak the\n"
103 " selected channel name.\n"
104 " r[(basename)] - Record the session to the monitor spool directory. An\n"
105 " optional base for the filename may be specified. The\n"
106 " default is 'chanspy'.\n"
107 " v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
108 " negative value refers to a quieter setting.\n"
109 " w - Enable 'whisper' mode, so the spying channel can talk to\n"
110 " the spied-on channel.\n"
111 " W - Enable 'private whisper' mode, so the spying channel can\n"
112 " talk to the spied-on channel but cannot listen to that\n"
117 OPTION_QUIET = (1 << 0), /* Quiet, no announcement */
118 OPTION_BRIDGED = (1 << 1), /* Only look at bridged calls */
119 OPTION_VOLUME = (1 << 2), /* Specify initial volume */
120 OPTION_GROUP = (1 << 3), /* Only look at channels in group */
121 OPTION_RECORD = (1 << 4),
122 OPTION_WHISPER = (1 << 5),
123 OPTION_PRIVATE = (1 << 6), /* Private Whisper mode */
133 AST_APP_OPTIONS(spy_opts, {
134 AST_APP_OPTION('q', OPTION_QUIET),
135 AST_APP_OPTION('b', OPTION_BRIDGED),
136 AST_APP_OPTION('w', OPTION_WHISPER),
137 AST_APP_OPTION('W', OPTION_PRIVATE),
138 AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
139 AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP),
140 AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
144 struct chanspy_translation_helper {
146 struct ast_channel_spy spy;
151 static void *spy_alloc(struct ast_channel *chan, void *data)
153 /* just store the data pointer in the channel structure */
157 static void spy_release(struct ast_channel *chan, void *data)
162 static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
164 struct chanspy_translation_helper *csth = data;
167 if (csth->spy.status != CHANSPY_RUNNING)
168 /* Channel is already gone more than likely */
171 ast_mutex_lock(&csth->spy.lock);
172 f = ast_channel_spy_read_frame(&csth->spy, samples);
173 ast_mutex_unlock(&csth->spy.lock);
178 if (ast_write(chan, f)) {
184 write(csth->fd, f->data, f->datalen);
191 static struct ast_generator spygen = {
193 .release = spy_release,
194 .generate = spy_generate,
197 static int start_spying(struct ast_channel *chan, struct ast_channel *spychan, struct ast_channel_spy *spy)
200 struct ast_channel *peer;
202 ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan->name, chan->name);
204 ast_channel_lock(chan);
205 res = ast_channel_spy_add(chan, spy);
206 ast_channel_unlock(chan);
208 if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan)))
209 ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
214 /* Map 'volume' levels from -4 through +4 into
215 decibel (dB) settings for channel drivers
217 static signed char volfactor_map[] = {
229 /* attempt to set the desired gain adjustment via the channel driver;
230 if successful, clear it out of the csth structure so the
231 generator will not attempt to do the adjustment itself
233 static void set_volume(struct ast_channel *chan, struct chanspy_translation_helper *csth)
235 signed char volume_adjust = volfactor_map[csth->volfactor + 4];
237 if (!ast_channel_setoption(chan, AST_OPTION_TXGAIN, &volume_adjust, sizeof(volume_adjust), 0))
239 csth->spy.read_vol_adjustment = csth->volfactor;
240 csth->spy.write_vol_adjustment = csth->volfactor;
243 static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int *volfactor, int fd,
244 const struct ast_flags *flags)
246 struct chanspy_translation_helper csth;
247 int running = 0, res, x = 0;
251 struct ast_silence_generator *silgen = NULL;
253 if (ast_check_hangup(chan) || ast_check_hangup(spyee))
256 name = ast_strdupa(spyee->name);
257 if (option_verbose >= 2)
258 ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name);
260 memset(&csth, 0, sizeof(csth));
261 ast_set_flag(&csth.spy, CHANSPY_FORMAT_AUDIO);
262 ast_set_flag(&csth.spy, CHANSPY_TRIGGER_NONE);
263 ast_set_flag(&csth.spy, CHANSPY_MIXAUDIO);
264 csth.spy.type = "ChanSpy";
265 csth.spy.status = CHANSPY_RUNNING;
266 csth.spy.read_queue.format = AST_FORMAT_SLINEAR;
267 csth.spy.write_queue.format = AST_FORMAT_SLINEAR;
268 ast_mutex_init(&csth.spy.lock);
269 csth.volfactor = *volfactor;
270 set_volume(chan, &csth);
271 if (csth.volfactor) {
272 ast_set_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
273 csth.spy.read_vol_adjustment = csth.volfactor;
274 ast_set_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
275 csth.spy.write_vol_adjustment = csth.volfactor;
279 if (start_spying(spyee, chan, &csth.spy)) {
280 ast_mutex_destroy(&csth.spy.lock);
284 if (ast_test_flag(flags, OPTION_WHISPER)) {
285 struct ast_filestream *beepstream;
286 int old_write_format = 0;
288 ast_channel_whisper_start(csth.spy.chan);
289 old_write_format = chan->writeformat;
290 if ((beepstream = ast_openstream_full(chan, "beep", chan->language, 1))) {
293 while ((f = ast_readframe(beepstream))) {
294 ast_channel_whisper_feed(csth.spy.chan, f);
298 ast_closestream(beepstream);
301 if (old_write_format)
302 ast_set_write_format(chan, old_write_format);
305 if (ast_test_flag(flags, OPTION_PRIVATE))
306 silgen = ast_channel_start_silence_generator(chan);
308 ast_activate_generator(chan, &spygen, &csth);
310 /* We can no longer rely on 'spyee' being an actual channel;
311 it can be hung up and freed out from under us. However, the
312 channel destructor will put NULL into our csth.spy.chan
313 field when that happens, so that is our signal that the spyee
314 channel has gone away.
317 /* Note: it is very important that the ast_waitfor() be the first
318 condition in this expression, so that if we wait for some period
319 of time before receiving a frame from our spying channel, we check
320 for hangup on the spied-on channel _after_ knowing that a frame
321 has arrived, since the spied-on channel could have gone away while
324 while ((res = ast_waitfor(chan, -1) > -1) &&
325 csth.spy.status == CHANSPY_RUNNING &&
327 if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
332 if (ast_test_flag(flags, OPTION_WHISPER) &&
333 (f->frametype == AST_FRAME_VOICE)) {
334 ast_channel_whisper_feed(csth.spy.chan, f);
339 res = (f->frametype == AST_FRAME_DTMF) ? f->subclass : 0;
344 if (x == sizeof(inp))
355 } else if (res == '#') {
356 if (!ast_strlen_zero(inp)) {
364 if (option_verbose > 2)
365 ast_verbose(VERBOSE_PREFIX_3 "Setting spy volume on %s to %d\n", chan->name, *volfactor);
366 csth.volfactor = *volfactor;
367 set_volume(chan, &csth);
368 if (csth.volfactor) {
369 ast_set_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
370 csth.spy.read_vol_adjustment = csth.volfactor;
371 ast_set_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
372 csth.spy.write_vol_adjustment = csth.volfactor;
374 ast_clear_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
375 ast_clear_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
377 } else if (res >= '0' && res <= '9') {
382 if (ast_test_flag(flags, OPTION_WHISPER) && csth.spy.chan)
383 ast_channel_whisper_stop(csth.spy.chan);
385 if (ast_test_flag(flags, OPTION_PRIVATE))
386 ast_channel_stop_silence_generator(chan, silgen);
388 ast_deactivate_generator(chan);
390 /* If a channel still exists on our spy structure then we need to remove ourselves */
392 csth.spy.status = CHANSPY_DONE;
393 ast_channel_lock(csth.spy.chan);
394 ast_channel_spy_remove(csth.spy.chan, &csth.spy);
395 ast_channel_unlock(csth.spy.chan);
397 ast_channel_spy_free(&csth.spy);
399 if (option_verbose >= 2)
400 ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
405 static struct ast_channel *next_channel(const struct ast_channel *last, const char *spec,
406 const char *exten, const char *context)
408 struct ast_channel *this;
412 this = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
414 this = ast_walk_channel_by_exten_locked(last, exten, context);
416 this = ast_channel_walk_locked(last);
419 ast_channel_unlock(this);
420 if (!strncmp(this->name, "Zap/pseudo", 10))
427 static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
428 int volfactor, const int fd, const char *mygroup, const char *spec,
429 const char *exten, const char *context)
431 struct ast_channel *peer, *prev, *next;
432 char nameprefix[AST_NAME_STRLEN];
433 char peer_name[AST_NAME_STRLEN + 5];
434 signed char zero_volume = 0;
440 if (chan->_state != AST_STATE_UP)
443 ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
448 if (!ast_test_flag(flags, OPTION_QUIET)) {
449 res = ast_streamfile(chan, "beep", chan->language);
451 res = ast_waitstream(chan, "");
453 ast_clear_flag(chan, AST_FLAG_SPYING);
458 res = ast_waitfordigit(chan, waitms);
460 ast_clear_flag(chan, AST_FLAG_SPYING);
464 /* reset for the next loop around, unless overridden later */
466 peer = prev = next = NULL;
468 for (peer = next_channel(peer, spec, exten, context);
470 prev = peer, peer = next ? next : next_channel(peer, spec, exten, context), next = NULL) {
485 if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(peer))
488 if (ast_check_hangup(peer) || ast_test_flag(peer, AST_FLAG_SPYING))
492 if ((group = pbx_builtin_getvar_helper(peer, "SPYGROUP"))) {
493 dup_group = ast_strdupa(group);
494 num_groups = ast_app_separate_args(dup_group, ':', groups,
495 sizeof(groups) / sizeof(groups[0]));
498 for (x = 0; x < num_groups; x++) {
499 if (!strcmp(mygroup, groups[x])) {
509 strcpy(peer_name, "spy-");
510 strncat(peer_name, peer->name, AST_NAME_STRLEN);
511 ptr = strchr(peer_name, '/');
514 for (s = peer_name; s < ptr; s++)
517 if (!ast_test_flag(flags, OPTION_QUIET)) {
518 if (ast_fileexists(peer_name, NULL, NULL) != -1) {
519 res = ast_streamfile(chan, peer_name, chan->language);
521 res = ast_waitstream(chan, "");
525 res = ast_say_character_str(chan, peer_name, "", chan->language);
526 if ((num = atoi(ptr)))
527 ast_say_digits(chan, atoi(ptr), "", chan->language);
531 res = channel_spy(chan, peer, &volfactor, fd, flags);
535 } else if (res > 1 && spec) {
536 snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);
537 if ((next = ast_get_channel_by_name_prefix_locked(nameprefix, strlen(nameprefix)))) {
538 ast_channel_unlock(next);
540 /* stay on this channel */
550 ast_clear_flag(chan, AST_FLAG_SPYING);
552 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
557 static int chanspy_exec(struct ast_channel *chan, void *data)
559 struct ast_module_user *u;
560 char *options = NULL;
563 char *mygroup = NULL;
564 char *recbase = NULL;
566 struct ast_flags flags;
572 data = ast_strdupa(data);
574 u = ast_module_user_add(chan);
576 if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
581 if (ast_strlen_zero(spec) || !strcmp(spec, "all"))
586 char *opts[OPT_ARG_ARRAY_SIZE];
588 ast_app_parse_options(spy_opts, &flags, opts, options);
589 if (ast_test_flag(&flags, OPTION_GROUP))
590 mygroup = opts[OPT_ARG_GROUP];
592 if (ast_test_flag(&flags, OPTION_RECORD) &&
593 !(recbase = opts[OPT_ARG_RECORD]))
596 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
599 if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
600 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
605 if (ast_test_flag(&flags, OPTION_PRIVATE))
606 ast_set_flag(&flags, OPTION_WHISPER);
609 oldwf = chan->writeformat;
610 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
611 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
612 ast_module_user_remove(u);
619 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
620 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) {
621 ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
626 res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL);
631 if (oldwf && ast_set_write_format(chan, oldwf) < 0)
632 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
634 ast_module_user_remove(u);
639 static int extenspy_exec(struct ast_channel *chan, void *data)
641 struct ast_module_user *u;
642 char *options = NULL;
644 char *context = NULL;
646 char *mygroup = NULL;
647 char *recbase = NULL;
649 struct ast_flags flags;
655 data = ast_strdupa(data);
657 u = ast_module_user_add(chan);
659 if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
661 if (!ast_strlen_zero(argv[0]))
662 exten = strsep(&context, "@");
663 if (ast_strlen_zero(context))
664 context = ast_strdupa(chan->context);
670 char *opts[OPT_ARG_ARRAY_SIZE];
672 ast_app_parse_options(spy_opts, &flags, opts, options);
673 if (ast_test_flag(&flags, OPTION_GROUP))
674 mygroup = opts[OPT_ARG_GROUP];
676 if (ast_test_flag(&flags, OPTION_RECORD) &&
677 !(recbase = opts[OPT_ARG_RECORD]))
680 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
683 if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
684 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
689 if (ast_test_flag(&flags, OPTION_PRIVATE))
690 ast_set_flag(&flags, OPTION_WHISPER);
693 oldwf = chan->writeformat;
694 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
695 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
696 ast_module_user_remove(u);
703 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
704 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) {
705 ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
710 res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context);
715 if (oldwf && ast_set_write_format(chan, oldwf) < 0)
716 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
718 ast_module_user_remove(u);
723 static int unload_module(void)
727 res |= ast_unregister_application(app_chan);
728 res |= ast_unregister_application(app_ext);
730 ast_module_user_hangup_all();
735 static int load_module(void)
739 res |= ast_register_application(app_chan, chanspy_exec, tdesc, desc_chan);
740 res |= ast_register_application(app_ext, extenspy_exec, tdesc, desc_ext);
745 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Listen to the audio of an active channel");