more optimizations
[asterisk/asterisk.git] / apps / app_chanspy.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * ChanSpy Listen in on any channel.
5  * 
6  * Copyright (C) 2005 Anthony Minessale II (anthmct@yahoo.com)
7  *
8  * Disclaimed to Digium
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/file.h>
15 #include <asterisk/logger.h>
16 #include <asterisk/channel.h>
17 #include <asterisk/features.h>
18 #include <asterisk/options.h>
19 #include <asterisk/app.h>
20 #include <asterisk/utils.h>
21 #include <asterisk/say.h>
22 #include <asterisk/pbx.h>
23 #include <asterisk/translate.h>
24 #include <asterisk/module.h>
25 #include <asterisk/lock.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <ctype.h>
30
31 AST_MUTEX_DEFINE_STATIC(modlock);
32
33 #define ast_fit_in_short(in) (in < -32768 ? -32768 : in > 32767 ? 32767 : in)
34 #define AST_NAME_STRLEN 256
35 #define ALL_DONE(u, ret) LOCAL_USER_REMOVE(u); return ret;
36 #define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
37 #define minmax(x,y) x ? (x > y) ? y : ((x < (y * -1)) ? (y * -1) : x) : 0
38 #define CS_BUFLEN 1024
39
40 static char *synopsis = "Tap into any type of asterisk channel and listen to audio";
41 static char *app = "ChanSpy";
42 static char *desc = "   Chanspy([<scanspec>][|<options>])\n\n"
43 "Valid Options:\n"
44 " - q: quiet, don't announce channels beep, etc.\n"
45 " - b: bridged, only spy on channels involved in a bridged call.\n"
46 " - v([-4..4]): adjust the initial volume. (negative is quieter)\n"
47 " - g(grp): enforce group.  Match only calls where their ${SPYGROUP} is 'grp'.\n\n"
48 "If <scanspec> is specified, only channel names *beginning* with that string will be scanned.\n"
49 "('all' or an empty string are also both valid <scanspec>)\n\n"
50 "While Spying:\n\n"
51 "Dialing # cycles the volume level.\n"
52 "Dialing * will stop spying and look for another channel to spy on.\n"
53 "Dialing a series of digits followed by # builds a channel name to append to <scanspec>\n"
54 "(e.g. run Chanspy(Agent) and dial 1234# while spying to jump to channel Agent/1234)\n\n"
55 "";
56
57 #define OPTION_QUIET     (1 << 0)       /* Quiet, no announcement */
58 #define OPTION_BRIDGED   (1 << 1)       /* Only look at bridged calls */
59 #define OPTION_VOLUME    (1 << 2)       /* Specify initial volume */
60 #define OPTION_GROUP     (1 << 3)   /* Only look at channels in group */
61
62 AST_DECLARE_OPTIONS(chanspy_opts,{
63         ['q'] = { OPTION_QUIET },
64         ['b'] = { OPTION_BRIDGED },
65         ['v'] = { OPTION_VOLUME, 1 },
66         ['g'] = { OPTION_GROUP, 2 },
67 });
68
69 STANDARD_LOCAL_USER;
70 LOCAL_USER_DECL;
71
72 struct chanspy_translation_helper {
73         /* spy data */
74         struct ast_channel_spy spy;
75
76         /* read frame */
77         int fmt0;
78         short buf0[CS_BUFLEN];
79         struct ast_trans_pvt *trans0;
80
81         /* write frame */
82         int fmt1;
83         struct ast_trans_pvt *trans1;
84         short buf1[CS_BUFLEN];
85         
86         /* muxed frame */
87         struct ast_frame frame;
88         short buf[CS_BUFLEN];
89
90         int volfactor;
91
92 };
93
94 /* Prototypes */
95 static struct ast_channel *local_get_channel_by_name(char *name);
96 static struct ast_channel *local_get_channel_begin_name(char *name);
97 static struct ast_channel *local_channel_walk(struct ast_channel *chan);
98 static void spy_release(struct ast_channel *chan, void *data);
99 static void *spy_alloc(struct ast_channel *chan, void *params);
100 static struct ast_frame *spy_queue_shift(struct ast_channel_spy *spy, int qnum);
101 static void ast_flush_spy_queue(struct ast_channel_spy *spy);
102 static int spy_generate(struct ast_channel *chan, void *data, int len, int samples);
103 static void start_spying(struct ast_channel *chan, struct ast_channel *spychan, struct ast_channel_spy *spy);
104 static void stop_spying(struct ast_channel *chan, struct ast_channel_spy *spy);
105 static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int *volfactor);
106 static int chanspy_exec(struct ast_channel *chan, void *data);
107
108
109 static struct ast_channel *local_get_channel_by_name(char *name) 
110 {
111         struct ast_channel *ret;
112         ast_mutex_lock(&modlock);
113         if ((ret = ast_get_channel_by_name_locked(name))) {
114                 ast_mutex_unlock(&ret->lock);
115         }
116         ast_mutex_unlock(&modlock);
117
118         return ret;
119 }
120
121 static struct ast_channel *local_channel_walk(struct ast_channel *chan) 
122 {
123         struct ast_channel *ret;
124         ast_mutex_lock(&modlock);       
125         if ((ret = ast_channel_walk_locked(chan))) {
126                 ast_mutex_unlock(&ret->lock);
127         }
128         ast_mutex_unlock(&modlock);                     
129         return ret;
130 }
131
132 static struct ast_channel *local_get_channel_begin_name(char *name) 
133 {
134         struct ast_channel *chan, *ret = NULL;
135         ast_mutex_lock(&modlock);
136         chan = local_channel_walk(NULL);
137         while (chan) {
138                 if (!strncmp(chan->name, name, strlen(name))) {
139                         ret = chan;
140                         break;
141                 }
142                 chan = local_channel_walk(chan);
143         }
144         ast_mutex_unlock(&modlock);
145         
146         return ret;
147 }
148
149
150 static void spy_release(struct ast_channel *chan, void *data) 
151 {
152         struct chanspy_translation_helper *csth = data;
153         int same=0;
154
155         same = (csth->trans0 == csth->trans1) ? 1 : 0;
156
157         if (csth->trans0) {
158                 ast_translator_free_path(csth->trans0);
159                 csth->trans0 = NULL;
160         }
161         if (same)
162                 return;
163         if (csth->trans1) {
164                 ast_translator_free_path(csth->trans1);
165                 csth->trans1 = NULL;
166         }
167         return;
168 }
169
170 static void *spy_alloc(struct ast_channel *chan, void *params) 
171 {
172         return params;
173 }
174
175 static struct ast_frame *spy_queue_shift(struct ast_channel_spy *spy, int qnum) 
176 {
177         struct ast_frame *f;
178         
179         if (qnum < 0 || qnum > 1)
180                 return NULL;
181
182         f = spy->queue[qnum];
183         if (f) {
184                 spy->queue[qnum] = f->next;
185                 return f;
186         }
187         return NULL;
188 }
189
190
191 static void ast_flush_spy_queue(struct ast_channel_spy *spy) 
192 {
193         struct ast_frame *f=NULL;
194         int x = 0;
195         ast_mutex_lock(&spy->lock);
196         for(x=0;x<2;x++) {
197                 f = NULL;
198                 while((f = spy_queue_shift(spy, x))) 
199                         ast_frfree(f);
200         }
201         ast_mutex_unlock(&spy->lock);
202 }
203
204 static int spy_generate(struct ast_channel *chan, void *data, int len, int samples) 
205 {
206         struct ast_frame *f, *f0, *f1;
207         int x = 0, vf = 0;
208
209         struct chanspy_translation_helper *csth = data;
210
211         ast_mutex_lock(&csth->spy.lock);
212         f0 = spy_queue_shift(&csth->spy, 0);
213         f1 = spy_queue_shift(&csth->spy, 1);
214         ast_mutex_unlock(&csth->spy.lock);
215         
216         if (!f0 && !f1) {
217                 return 0;
218         }
219
220         if (f0 && csth->fmt0 && csth->fmt0 != f0->subclass) {
221                 ast_translator_free_path(csth->trans0);
222         csth->trans0 = NULL;
223                 csth->fmt0 = csth->fmt0;
224         }
225
226         if (f1 && csth->fmt1 && csth->fmt1 != f1->subclass) {
227                 ast_translator_free_path(csth->trans1);
228         csth->trans1 = NULL;
229                 csth->fmt1 = csth->fmt1;
230         }
231         
232         if (!csth->fmt0 && f0) {
233                 csth->fmt0 = f0->subclass;
234         }
235
236         if (!csth->fmt1 && f1) {
237                 csth->fmt1 = f1->subclass;
238         }
239
240         if (csth->fmt0 && csth->fmt0 != AST_FORMAT_SLINEAR && !csth->trans0) {
241                 if (csth->fmt0 == csth->fmt1 && csth->trans1) {
242                         csth->trans0 = csth->trans1;
243                 } else if ((csth->trans0 = ast_translator_build_path(AST_FORMAT_SLINEAR, csth->fmt0)) == NULL) {
244                         ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(csth->fmt0));
245                         return -1;
246                 }
247         }
248         
249         if (csth->fmt1 && csth->fmt1 != AST_FORMAT_SLINEAR && !csth->trans1) {
250                 if (csth->fmt1 == csth->fmt0 && csth->trans0) {
251                         csth->trans1 = csth->trans0;
252                 } else if ((csth->trans1 = ast_translator_build_path(AST_FORMAT_SLINEAR, csth->fmt1)) == NULL) {
253                         ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(csth->fmt1));
254                         return -1;
255                 }
256         }
257         
258         if (f0) {
259                 if (csth->trans0) {
260                         if ((f = ast_translate(csth->trans0, f0, 0))) {
261                                 memcpy(csth->buf0, f->data, f->datalen * sizeof(short));
262                                 ast_frfree(f);
263                         } else {
264                                 return 0;
265                         }
266                 } else {
267                         memcpy(csth->buf0, f0->data, f0->datalen * sizeof(short));
268                 }
269         }
270         
271         if (f1) {
272                 if (csth->trans1) {
273                         if ((f = ast_translate(csth->trans1, f1, 0))) {
274                                 memcpy(csth->buf1, f->data, f->datalen * sizeof(short));
275                                 ast_frfree(f);
276                         } else {
277                                 return 0;
278                         }
279                 } else {
280                         memcpy(csth->buf1, f1->data, f1->datalen * sizeof(short));
281                 }
282         }
283
284         vf = get_volfactor(csth->volfactor);
285         vf = minmax(vf, 16);
286         for(x=0; x < len; x++) {
287                 if (vf < 0) {
288                         if (f0) {
289                                 csth->buf0[x] /= abs(vf);
290                         }
291                         if (f1) {
292                                 csth->buf1[x] /= abs(vf);
293                         }
294                 } else if (vf > 0) {
295                         if (f0) {
296                                 csth->buf0[x] *= vf;
297                         }
298                         if (f1) {
299                                 csth->buf1[x] *= vf;
300                         }
301                 }
302                 if (f0 && f1) {
303                         csth->buf[x] = ast_fit_in_short(csth->buf0[x] + csth->buf1[x]);
304                 } else if (f0) {
305                         csth->buf[x] = csth->buf0[x];
306                 } else if (f1) {
307                         csth->buf[x] = csth->buf1[x];
308                 }
309         }
310
311         csth->frame.data = csth->buf;
312         ast_write(chan, &csth->frame);
313
314         if (f0) {
315                 ast_frfree(f0);
316         }
317         if (f1) {
318                 ast_frfree(f1);
319         }
320
321         return 0;
322 }
323
324 static struct ast_generator spygen = {
325     alloc: spy_alloc, 
326     release: spy_release, 
327     generate: spy_generate, 
328 };
329
330 static void start_spying(struct ast_channel *chan, struct ast_channel *spychan, struct ast_channel_spy *spy) 
331 {
332
333         struct ast_channel_spy *cptr=NULL;
334         struct ast_channel *peer;
335
336
337         ast_log(LOG_WARNING, "Attaching %s to %s\n", spychan->name, chan->name);
338
339
340         ast_mutex_lock(&chan->lock);
341         if (chan->spiers) {
342                 for(cptr=chan->spiers;cptr && cptr->next;cptr=cptr->next);
343                 cptr->next = spy;
344         } else {
345                 chan->spiers = spy;
346         }
347         ast_mutex_unlock(&chan->lock);
348         if ( ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) {
349                 ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);  
350         }
351
352 }
353
354 static void stop_spying(struct ast_channel *chan, struct ast_channel_spy *spy) 
355 {
356         struct ast_channel_spy *cptr=NULL, *prev=NULL;
357         int count = 0;
358
359         while(ast_mutex_trylock(&chan->lock)) {
360                 /* if its locked already it's almost surely hanging up and we are too late 
361                    we can safely remove the head pointer if it points at us without needing a lock.
362                    since everybody spying will be in the same boat whomever is pointing at the head
363                    will surely erase it which is all we really need since it's a linked list of
364                    staticly declared structs that belong to each spy.
365                 */
366                 if (chan->spiers == spy) {
367                         chan->spiers = NULL;
368                         return;
369                 }
370                 count++;
371                 if(count > 10) {
372                         return;
373                 }
374                 sched_yield();
375         }
376
377         for(cptr=chan->spiers; cptr; cptr=cptr->next) {
378                 if (cptr == spy) {
379                         if (prev) {
380                                 prev->next = cptr->next;
381                                 cptr->next = NULL;
382                         } else
383                                 chan->spiers = NULL;
384                 }
385                 prev = cptr;
386         }
387         ast_mutex_unlock(&chan->lock);
388
389 }
390
391 static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int *volfactor) 
392 {
393         struct chanspy_translation_helper csth;
394         int running = 1, res = 0, x = 0;
395         char inp[24];
396         char *name=NULL;
397         struct ast_frame *f;
398
399         if (chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee)) {
400                 memset(inp, 0, sizeof(inp));
401                 name = ast_strdupa(spyee->name);
402                 if (option_verbose >= 2)
403                         ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name);
404
405                 memset(&csth, 0, sizeof(csth));
406                 csth.spy.status = CHANSPY_RUNNING;
407                 ast_mutex_init(&csth.spy.lock);
408                 csth.volfactor = *volfactor;
409                 csth.frame.frametype = AST_FRAME_VOICE;
410                 csth.frame.subclass = AST_FORMAT_SLINEAR;
411                 csth.frame.datalen = 320;
412                 csth.frame.samples = 160;
413                 start_spying(spyee, chan, &csth.spy);
414                 ast_activate_generator(chan, &spygen, &csth);
415
416                 while(csth.spy.status == CHANSPY_RUNNING && 
417                           chan && !ast_check_hangup(chan) && 
418                           spyee && 
419                           !ast_check_hangup(spyee) 
420                           && running == 1 && 
421                           (res = ast_waitfor(chan, -1) > -1)) {
422                         if ((f = ast_read(chan))) {
423                                 res = 0;
424                                 if(f->frametype == AST_FRAME_DTMF) {
425                                         res = f->subclass;
426                                 }
427                                 ast_frfree(f);
428                                 if(!res) {
429                                         continue;
430                                 }
431                         }
432                         if (x == sizeof(inp)) {
433                                 x = 0;
434                         }
435                         if (res < 0) {
436                                 running = -1;
437                         }
438                         if (res == 0) {
439                                 continue;
440                         } else if (res == '*') {
441                                 running = 0; 
442                         } else if (res == '#') {
443                                 if (!ast_strlen_zero(inp)) {
444                                         running = x ? atoi(inp) : -1;
445                                         break;
446                                 } else {
447                                         csth.volfactor++;
448                                         if (csth.volfactor > 4) {
449                                                 csth.volfactor = -4;
450                                         }
451                                         if (option_verbose > 2) {
452                                                 ast_verbose(VERBOSE_PREFIX_3"Setting spy volume on %s to %d\n", chan->name, csth.volfactor);
453                                         }
454                                         *volfactor = csth.volfactor;
455                                 }
456                         } else if (res >= 48 && res <= 57) {
457                                 inp[x++] = res;
458                         }
459                 }
460                 ast_deactivate_generator(chan);
461                 stop_spying(spyee, &csth.spy);
462
463                 if (option_verbose >= 2) {
464                         ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
465                 }
466                 ast_flush_spy_queue(&csth.spy);
467         } else {
468                 running = 0;
469         }
470         ast_mutex_destroy(&csth.spy.lock);
471         return running;
472 }
473
474
475
476 static int chanspy_exec(struct ast_channel *chan, void *data)
477 {
478         struct localuser *u;
479         struct ast_channel *peer=NULL, *prev=NULL;
480         char name[AST_NAME_STRLEN],
481                 peer_name[AST_NAME_STRLEN],
482                 *args,
483                 *ptr = NULL,
484                 *options = NULL,
485                 *spec = NULL,
486                 *argv[5],
487                 *mygroup = NULL;
488         int res = -1,
489                 volfactor = 0,
490                 silent = 0,
491                 argc = 0,
492                 bronly = 0,
493                 chosen = 0,
494                 count=0,
495                 waitms = 100,
496                 num = 0;
497         struct ast_flags flags;
498
499
500         if (!(args = ast_strdupa((char *)data))) {
501                 ast_log(LOG_ERROR, "Out of memory!\n");
502                 return -1;
503         }
504
505         if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
506                 ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
507                 return -1;
508         }
509         
510         if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
511                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
512                 return -1;
513         }
514
515         LOCAL_USER_ADD(u);
516         ast_answer(chan);
517
518         ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
519
520
521         if ((argc = ast_separate_app_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
522                 spec = argv[0];
523                 if ( argc > 1) {
524                         options = argv[1];
525                 }
526                 if (ast_strlen_zero(spec) || !strcmp(spec, "all")) {
527                         spec = NULL;
528                 }
529         }
530         
531         if (options) {
532                 char *opts[2];
533                 ast_parseoptions(chanspy_opts, &flags, opts, options);
534                 if (ast_test_flag(&flags, OPTION_GROUP)) {
535                         mygroup = opts[1];
536                 }
537                 silent = ast_test_flag(&flags, OPTION_QUIET);
538                 bronly = ast_test_flag(&flags, OPTION_BRIDGED);
539                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[1]) {
540                         if (sscanf(opts[0], "%d", &volfactor) != 1)
541                                 ast_log(LOG_NOTICE, "volfactor must be a number between -4 and 4\n");
542                         else {
543                                 volfactor = minmax(volfactor, 4);
544                         }
545                 }
546         }
547
548
549         for(;;) {
550                 res = ast_streamfile(chan, "beep", chan->language);
551                 if (!res)
552                         res = ast_waitstream(chan, "");
553                 if (res < 0) {
554                         ast_clear_flag(chan, AST_FLAG_SPYING);
555                         ALL_DONE(u, -1);
556                 }                       
557
558                 count = 0;
559                 res = ast_waitfordigit(chan, waitms);
560                 if (res < 0) {
561                         ast_clear_flag(chan, AST_FLAG_SPYING);
562                         ALL_DONE(u, -1);
563                 }
564                                 
565                 peer = local_channel_walk(NULL);
566                 prev=NULL;
567                 while(peer) {
568                         if (peer != chan) {
569                                 char *group = NULL;
570                                 int igrp = 1;
571
572                                 if (peer == prev && !chosen) {
573                                         break;
574                                 }
575                                 chosen = 0;
576                                 group = pbx_builtin_getvar_helper(peer, "SPYGROUP");
577                                 if (mygroup) {
578                                         if (!group || strcmp(mygroup, group)) {
579                                                 igrp = 0;
580                                         }
581                                 }
582                                 
583                                 if (igrp && (!spec || ((strlen(spec) < strlen(peer->name) &&
584                                                                            !strncasecmp(peer->name, spec, strlen(spec)))))) {
585                                         if (peer && (!bronly || ast_bridged_channel(peer)) &&
586                                                 !ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
587                                                 int x = 0;
588
589                                                 strncpy(peer_name, peer->name, AST_NAME_STRLEN);
590                                                 ptr = strchr(peer_name, '/');
591                                                 *ptr = '\0';
592                                                 ptr++;
593                                                 for (x = 0 ; x < strlen(peer_name) ; x++) {
594                                                         if(peer_name[x] == '/') {
595                                                                 break;
596                                                         }
597                                                         peer_name[x] = tolower(peer_name[x]);
598                                                 }
599
600                                                 if (!silent) {
601                                                         if (ast_fileexists(peer_name, NULL, NULL) != -1) {
602                                                                 res = ast_streamfile(chan, peer_name, chan->language);
603                                                                 if (!res)
604                                                                         res = ast_waitstream(chan, "");
605                                                                 if (res)
606                                                                         break;
607                                                         } else
608                                                                 res = ast_say_character_str(chan, peer_name, "", chan->language);
609                                                         if ((num=atoi(ptr))) 
610                                                                 ast_say_digits(chan, atoi(ptr), "", chan->language);
611                                                 }
612                                                 count++;
613                                                 prev = peer;
614                                                 res = channel_spy(chan, peer, &volfactor);
615                                                 if (res == -1) {
616                                                         ast_clear_flag(chan, AST_FLAG_SPYING);
617                                                         ALL_DONE(u, -1);
618                                                 } else if (res > 1 && spec) {
619                                                         snprintf(name, AST_NAME_STRLEN, "%s/%d", spec, res);
620                                                         if ((peer = local_get_channel_begin_name(name))) {
621                                                                 chosen = 1;
622                                                         }
623                                                         continue;
624                                                 }
625                                         }
626                                 }
627                         }
628                         if ((peer = local_channel_walk(peer)) == NULL) {
629                                 break;
630                         }
631                 }
632                 waitms = count ? 100 : 5000;
633         }
634         
635
636         ast_clear_flag(chan, AST_FLAG_SPYING);
637         ALL_DONE(u, res);
638 }
639
640 int unload_module(void)
641 {
642         STANDARD_HANGUP_LOCALUSERS;
643         return ast_unregister_application(app);
644 }
645
646 int load_module(void)
647 {
648         return ast_register_application(app, chanspy_exec, synopsis, desc);
649 }
650
651 char *description(void)
652 {
653         return synopsis;
654 }
655
656 int usecount(void)
657 {
658         int res;
659         STANDARD_USECOUNT(res);
660         return res;
661 }
662
663 char *key()
664 {
665         return ASTERISK_GPL_KEY;
666 }