00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <unistd.h>
00030 #include <ctype.h>
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 45060 $")
00035
00036 #include "asterisk/file.h"
00037 #include "asterisk/logger.h"
00038 #include "asterisk/channel.h"
00039 #include "asterisk/chanspy.h"
00040 #include "asterisk/features.h"
00041 #include "asterisk/options.h"
00042 #include "asterisk/app.h"
00043 #include "asterisk/utils.h"
00044 #include "asterisk/say.h"
00045 #include "asterisk/pbx.h"
00046 #include "asterisk/translate.h"
00047 #include "asterisk/module.h"
00048 #include "asterisk/lock.h"
00049
00050 AST_MUTEX_DEFINE_STATIC(modlock);
00051
00052 #define AST_NAME_STRLEN 256
00053 #define ALL_DONE(u, ret) LOCAL_USER_REMOVE(u); return ret;
00054 #define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
00055
00056 static const char *synopsis = "Listen to the audio of an active channel\n";
00057 static const char *app = "ChanSpy";
00058 static const char *desc =
00059 " ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
00060 "audio from an active Asterisk channel. This includes the audio coming in and\n"
00061 "out of the channel being spied on. If the 'chanprefix' parameter is specified,\n"
00062 "only channels beginning with this string will be spied upon.\n"
00063 " While Spying, the following actions may be performed:\n"
00064 " - Dialing # cycles the volume level.\n"
00065 " - Dialing * will stop spying and look for another channel to spy on.\n"
00066 " - Dialing a series of digits followed by # builds a channel name to append\n"
00067 " to 'chanprefix'. For example, executing ChanSpy(Agent) and then dialing\n"
00068 " the digits '1234#' while spying will begin spying on the channel,\n"
00069 " 'Agent/1234'.\n"
00070 " Options:\n"
00071 " b - Only spy on channels involved in a bridged call.\n"
00072 " g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n"
00073 " 'grp'.\n"
00074 " q - Don't play a beep when beginning to spy on a channel.\n"
00075 " r[(basename)] - Record the session to the monitor spool directory. An\n"
00076 " optional base for the filename may be specified. The\n"
00077 " default is 'chanspy'.\n"
00078 " v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
00079 " negative value refers to a quieter setting.\n"
00080 ;
00081
00082 static const char *chanspy_spy_type = "ChanSpy";
00083
00084 enum {
00085 OPTION_QUIET = (1 << 0),
00086 OPTION_BRIDGED = (1 << 1),
00087 OPTION_VOLUME = (1 << 2),
00088 OPTION_GROUP = (1 << 3),
00089 OPTION_RECORD = (1 << 4),
00090 } chanspy_opt_flags;
00091
00092 enum {
00093 OPT_ARG_VOLUME = 0,
00094 OPT_ARG_GROUP,
00095 OPT_ARG_RECORD,
00096 OPT_ARG_ARRAY_SIZE,
00097 } chanspy_opt_args;
00098
00099 AST_APP_OPTIONS(chanspy_opts, {
00100 AST_APP_OPTION('q', OPTION_QUIET),
00101 AST_APP_OPTION('b', OPTION_BRIDGED),
00102 AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
00103 AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP),
00104 AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
00105 });
00106
00107 STANDARD_LOCAL_USER;
00108 LOCAL_USER_DECL;
00109
00110 struct chanspy_translation_helper {
00111
00112 struct ast_channel_spy spy;
00113 int fd;
00114 int volfactor;
00115 };
00116
00117 static struct ast_channel *local_channel_walk(struct ast_channel *chan)
00118 {
00119 struct ast_channel *ret;
00120 ast_mutex_lock(&modlock);
00121 if ((ret = ast_channel_walk_locked(chan))) {
00122 ast_mutex_unlock(&ret->lock);
00123 }
00124 ast_mutex_unlock(&modlock);
00125 return ret;
00126 }
00127
00128 static struct ast_channel *local_get_channel_begin_name(char *name)
00129 {
00130 struct ast_channel *chan, *ret = NULL;
00131 ast_mutex_lock(&modlock);
00132 chan = local_channel_walk(NULL);
00133 while (chan) {
00134 if (!strncmp(chan->name, name, strlen(name)) && strncmp(chan->name, "Zap/pseudo", 10)) {
00135 ret = chan;
00136 break;
00137 }
00138 chan = local_channel_walk(chan);
00139 }
00140 ast_mutex_unlock(&modlock);
00141
00142 return ret;
00143 }
00144
00145 static void *spy_alloc(struct ast_channel *chan, void *data)
00146 {
00147
00148 return data;
00149 }
00150
00151 static void spy_release(struct ast_channel *chan, void *data)
00152 {
00153
00154 }
00155
00156 static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
00157 {
00158 struct chanspy_translation_helper *csth = data;
00159 struct ast_frame *f;
00160
00161 if (csth->spy.status != CHANSPY_RUNNING)
00162
00163 return -1;
00164
00165 ast_mutex_lock(&csth->spy.lock);
00166 f = ast_channel_spy_read_frame(&csth->spy, samples);
00167 ast_mutex_unlock(&csth->spy.lock);
00168
00169 if (!f)
00170 return 0;
00171
00172 if (ast_write(chan, f)) {
00173 ast_frfree(f);
00174 return -1;
00175 }
00176
00177 if (csth->fd)
00178 write(csth->fd, f->data, f->datalen);
00179
00180 ast_frfree(f);
00181
00182 return 0;
00183 }
00184
00185
00186 static struct ast_generator spygen = {
00187 .alloc = spy_alloc,
00188 .release = spy_release,
00189 .generate = spy_generate,
00190 };
00191
00192 static int start_spying(struct ast_channel *chan, struct ast_channel *spychan, struct ast_channel_spy *spy)
00193 {
00194 int res;
00195 struct ast_channel *peer;
00196
00197 ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan->name, chan->name);
00198
00199 ast_mutex_lock(&chan->lock);
00200 res = ast_channel_spy_add(chan, spy);
00201 ast_mutex_unlock(&chan->lock);
00202
00203 if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) {
00204 ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
00205 }
00206
00207 return res;
00208 }
00209
00210
00211
00212
00213 static signed char volfactor_map[] = {
00214 -24,
00215 -18,
00216 -12,
00217 -6,
00218 0,
00219 6,
00220 12,
00221 18,
00222 24,
00223 };
00224
00225
00226
00227
00228
00229 static void set_volume(struct ast_channel *chan, struct chanspy_translation_helper *csth)
00230 {
00231 signed char volume_adjust = volfactor_map[csth->volfactor + 4];
00232
00233 if (!ast_channel_setoption(chan, AST_OPTION_TXGAIN, &volume_adjust, sizeof(volume_adjust), 0))
00234 csth->volfactor = 0;
00235 }
00236
00237 static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int *volfactor, int fd)
00238 {
00239 struct chanspy_translation_helper csth;
00240 int running = 0, res = 0, x = 0;
00241 char inp[24] = "", *name = NULL;
00242 struct ast_frame *f = NULL;
00243
00244 if ((chan && ast_check_hangup(chan)) || (spyee && ast_check_hangup(spyee)))
00245 return 0;
00246
00247 name = ast_strdupa(spyee->name);
00248 if (option_verbose > 1)
00249 ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name);
00250
00251 memset(&csth, 0, sizeof(csth));
00252 ast_set_flag(&csth.spy, CHANSPY_FORMAT_AUDIO);
00253 ast_set_flag(&csth.spy, CHANSPY_TRIGGER_NONE);
00254 ast_set_flag(&csth.spy, CHANSPY_MIXAUDIO);
00255 csth.spy.type = chanspy_spy_type;
00256 csth.spy.status = CHANSPY_RUNNING;
00257 csth.spy.read_queue.format = AST_FORMAT_SLINEAR;
00258 csth.spy.write_queue.format = AST_FORMAT_SLINEAR;
00259 ast_mutex_init(&csth.spy.lock);
00260 csth.volfactor = *volfactor;
00261 set_volume(chan, &csth);
00262 if (csth.volfactor) {
00263 ast_set_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
00264 csth.spy.read_vol_adjustment = csth.volfactor;
00265 ast_set_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
00266 csth.spy.write_vol_adjustment = csth.volfactor;
00267 }
00268 csth.fd = fd;
00269
00270 if (start_spying(spyee, chan, &csth.spy)) {
00271 ast_channel_spy_free(&csth.spy);
00272 return 0;
00273 }
00274
00275 ast_activate_generator(chan, &spygen, &csth);
00276
00277 while (csth.spy.status == CHANSPY_RUNNING &&
00278 (res = ast_waitfor(chan, -1) > -1)) {
00279
00280
00281 if (!(f = ast_read(chan)))
00282 break;
00283
00284
00285 res = 0;
00286 if (f->frametype == AST_FRAME_DTMF)
00287 res = f->subclass;
00288 ast_frfree(f);
00289 if (!res)
00290 continue;
00291
00292 if (x == sizeof(inp))
00293 x = 0;
00294
00295 if (res < 0) {
00296 running = -1;
00297 break;
00298 }
00299
00300
00301 if (res == '#') {
00302 if (!ast_strlen_zero(inp)) {
00303 running = x ? atoi(inp) : -1;
00304 break;
00305 } else {
00306 (*volfactor)++;
00307 if (*volfactor > 4)
00308 *volfactor = -1;
00309 if (option_verbose > 2)
00310 ast_verbose(VERBOSE_PREFIX_3 "Setting spy volume on %s to %d\n", chan->name, *volfactor);
00311 csth.volfactor = *volfactor;
00312 set_volume(chan, &csth);
00313 if (csth.volfactor) {
00314 ast_set_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
00315 csth.spy.read_vol_adjustment = csth.volfactor;
00316 ast_set_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
00317 csth.spy.write_vol_adjustment = csth.volfactor;
00318 } else {
00319 ast_clear_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
00320 ast_clear_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
00321 }
00322 }
00323 } else if (res == '*') {
00324 break;
00325 } else if (res >= 48 && res <= 57) {
00326 inp[x++] = res;
00327 }
00328 }
00329
00330 ast_deactivate_generator(chan);
00331
00332 ast_mutex_lock(&csth.spy.lock);
00333 if (csth.spy.chan) {
00334 csth.spy.status = CHANSPY_DONE;
00335 ast_mutex_lock(&csth.spy.chan->lock);
00336 ast_channel_spy_remove(csth.spy.chan, &csth.spy);
00337 ast_mutex_unlock(&csth.spy.chan->lock);
00338 }
00339 ast_mutex_unlock(&csth.spy.lock);
00340
00341 if (option_verbose > 1)
00342 ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
00343
00344 ast_channel_spy_free(&csth.spy);
00345
00346 return running;
00347 }
00348
00349 static int chanspy_exec(struct ast_channel *chan, void *data)
00350 {
00351 struct localuser *u;
00352 struct ast_channel *peer=NULL, *prev=NULL;
00353 char name[AST_NAME_STRLEN],
00354 peer_name[AST_NAME_STRLEN + 5],
00355 *args,
00356 *ptr = NULL,
00357 *options = NULL,
00358 *spec = NULL,
00359 *argv[5],
00360 *mygroup = NULL,
00361 *recbase = NULL;
00362 int res = -1,
00363 volfactor = 0,
00364 silent = 0,
00365 argc = 0,
00366 bronly = 0,
00367 chosen = 0,
00368 count=0,
00369 waitms = 100,
00370 num = 0,
00371 oldrf = 0,
00372 oldwf = 0,
00373 fd = 0;
00374 struct ast_flags flags;
00375 signed char zero_volume = 0;
00376
00377 if (!(args = ast_strdupa((char *)data))) {
00378 ast_log(LOG_ERROR, "Out of memory!\n");
00379 return -1;
00380 }
00381
00382 LOCAL_USER_ADD(u);
00383
00384 oldrf = chan->readformat;
00385 oldwf = chan->writeformat;
00386 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
00387 ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
00388 LOCAL_USER_REMOVE(u);
00389 return -1;
00390 }
00391
00392 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
00393 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
00394 LOCAL_USER_REMOVE(u);
00395 return -1;
00396 }
00397
00398 ast_answer(chan);
00399
00400 ast_set_flag(chan, AST_FLAG_SPYING);
00401
00402 if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
00403 spec = argv[0];
00404 if ( argc > 1) {
00405 options = argv[1];
00406 }
00407 if (ast_strlen_zero(spec) || !strcmp(spec, "all")) {
00408 spec = NULL;
00409 }
00410 }
00411
00412 if (options) {
00413 char *opts[OPT_ARG_ARRAY_SIZE];
00414 ast_app_parse_options(chanspy_opts, &flags, opts, options);
00415 if (ast_test_flag(&flags, OPTION_GROUP)) {
00416 mygroup = opts[OPT_ARG_GROUP];
00417 }
00418 if (ast_test_flag(&flags, OPTION_RECORD)) {
00419 if (!(recbase = opts[OPT_ARG_RECORD])) {
00420 recbase = "chanspy";
00421 }
00422 }
00423 silent = ast_test_flag(&flags, OPTION_QUIET);
00424 bronly = ast_test_flag(&flags, OPTION_BRIDGED);
00425 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
00426 int vol;
00427
00428 if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
00429 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
00430 else
00431 volfactor = vol;
00432 }
00433 }
00434
00435 if (recbase) {
00436 char filename[512];
00437 snprintf(filename,sizeof(filename),"%s/%s.%d.raw",ast_config_AST_MONITOR_DIR, recbase, (int)time(NULL));
00438 if ((fd = open(filename, O_CREAT | O_WRONLY, O_TRUNC, 0644)) <= 0) {
00439 ast_log(LOG_WARNING, "Cannot open %s for recording\n", filename);
00440 fd = 0;
00441 }
00442 }
00443
00444 for(;;) {
00445 if (!silent) {
00446 res = ast_streamfile(chan, "beep", chan->language);
00447 if (!res)
00448 res = ast_waitstream(chan, "");
00449 if (res < 0) {
00450 ast_clear_flag(chan, AST_FLAG_SPYING);
00451 break;
00452 }
00453 }
00454
00455 count = 0;
00456 res = ast_waitfordigit(chan, waitms);
00457 if (res < 0) {
00458 ast_clear_flag(chan, AST_FLAG_SPYING);
00459 break;
00460 }
00461
00462 peer = local_channel_walk(NULL);
00463 prev=NULL;
00464 while(peer) {
00465 if (peer != chan) {
00466 char *group = NULL;
00467 int igrp = 1;
00468
00469 if (peer == prev && !chosen) {
00470 break;
00471 }
00472 chosen = 0;
00473 group = pbx_builtin_getvar_helper(peer, "SPYGROUP");
00474 if (mygroup) {
00475 if (!group || strcmp(mygroup, group)) {
00476 igrp = 0;
00477 }
00478 }
00479
00480 if (igrp && (!spec || ((strlen(spec) <= strlen(peer->name) &&
00481 !strncasecmp(peer->name, spec, strlen(spec)))))) {
00482 if (peer && (!bronly || ast_bridged_channel(peer)) &&
00483 !ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
00484 int x = 0;
00485 strncpy(peer_name, "spy-", 5);
00486 strncpy(peer_name + strlen(peer_name), peer->name, AST_NAME_STRLEN);
00487 ptr = strchr(peer_name, '/');
00488 *ptr = '\0';
00489 ptr++;
00490 for (x = 0 ; x < strlen(peer_name) ; x++) {
00491 if (peer_name[x] == '/') {
00492 break;
00493 }
00494 peer_name[x] = tolower(peer_name[x]);
00495 }
00496
00497 if (!silent) {
00498 if (ast_fileexists(peer_name, NULL, NULL) != -1) {
00499 res = ast_streamfile(chan, peer_name, chan->language);
00500 if (!res)
00501 res = ast_waitstream(chan, "");
00502 if (res)
00503 break;
00504 } else
00505 res = ast_say_character_str(chan, peer_name, "", chan->language);
00506 if ((num=atoi(ptr)))
00507 ast_say_digits(chan, atoi(ptr), "", chan->language);
00508 }
00509 count++;
00510 prev = peer;
00511 res = channel_spy(chan, peer, &volfactor, fd);
00512 if (res == -1) {
00513 break;
00514 } else if (res > 1 && spec) {
00515 snprintf(name, AST_NAME_STRLEN, "%s/%d", spec, res);
00516 if ((peer = local_get_channel_begin_name(name))) {
00517 chosen = 1;
00518 }
00519 continue;
00520 }
00521 }
00522 }
00523 }
00524 if ((peer = local_channel_walk(peer)) == NULL) {
00525 break;
00526 }
00527 }
00528 waitms = count ? 100 : 5000;
00529 }
00530
00531
00532 if (fd > 0) {
00533 close(fd);
00534 }
00535
00536 if (oldrf && ast_set_read_format(chan, oldrf) < 0) {
00537 ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
00538 }
00539
00540 if (oldwf && ast_set_write_format(chan, oldwf) < 0) {
00541 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
00542 }
00543
00544 ast_clear_flag(chan, AST_FLAG_SPYING);
00545
00546 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
00547
00548 ALL_DONE(u, res);
00549 }
00550
00551 int unload_module(void)
00552 {
00553 int res;
00554
00555 res = ast_unregister_application(app);
00556
00557 STANDARD_HANGUP_LOCALUSERS;
00558
00559 return res;
00560 }
00561
00562 int load_module(void)
00563 {
00564 return ast_register_application(app, chanspy_exec, synopsis, desc);
00565 }
00566
00567 char *description(void)
00568 {
00569 return (char *) synopsis;
00570 }
00571
00572 int usecount(void)
00573 {
00574 int res;
00575 STANDARD_USECOUNT(res);
00576 return res;
00577 }
00578
00579 char *key()
00580 {
00581 return ASTERISK_GPL_KEY;
00582 }