Don't do SIP contact/route DNS if we're not using the result.
[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 /*** MODULEINFO
33         <support_level>core</support_level>
34  ***/
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include <ctype.h>
41 #include <errno.h>
42
43 #include "asterisk/paths.h" /* use ast_config_AST_MONITOR_DIR */
44 #include "asterisk/file.h"
45 #include "asterisk/channel.h"
46 #include "asterisk/audiohook.h"
47 #include "asterisk/features.h"
48 #include "asterisk/app.h"
49 #include "asterisk/utils.h"
50 #include "asterisk/say.h"
51 #include "asterisk/pbx.h"
52 #include "asterisk/translate.h"
53 #include "asterisk/manager.h"
54 #include "asterisk/module.h"
55 #include "asterisk/lock.h"
56 #include "asterisk/options.h"
57 #include "asterisk/autochan.h"
58
59 #define AST_NAME_STRLEN 256
60 #define NUM_SPYGROUPS 128
61
62 /*** DOCUMENTATION
63         <application name="ChanSpy" language="en_US">
64                 <synopsis>
65                         Listen to a channel, and optionally whisper into it.
66                 </synopsis>
67                 <syntax>
68                         <parameter name="chanprefix" />
69                         <parameter name="options">
70                                 <optionlist>
71                                         <option name="b">
72                                                 <para>Only spy on channels involved in a bridged call.</para>
73                                         </option>
74                                         <option name="B">
75                                                 <para>Instead of whispering on a single channel barge in on both
76                                                 channels involved in the call.</para>
77                                         </option>
78                                         <option name="c">
79                                                 <argument name="digit" required="true">
80                                                         <para>Specify a DTMF digit that can be used to spy on the next available channel.</para>
81                                                 </argument>
82                                         </option>
83                                         <option name="d">
84                                                 <para>Override the typical numeric DTMF functionality and instead
85                                                 use DTMF to switch between spy modes.</para>
86                                                 <enumlist>
87                                                         <enum name="4">
88                                                                 <para>spy mode</para>
89                                                         </enum>
90                                                         <enum name="5">
91                                                                 <para>whisper mode</para>
92                                                         </enum>
93                                                         <enum name="6">
94                                                                 <para>barge mode</para>
95                                                         </enum>
96                                                 </enumlist>
97                                         </option>
98                                         <option name="e">
99                                                 <argument name="ext" required="true" />
100                                                 <para>Enable <emphasis>enforced</emphasis> mode, so the spying channel can
101                                                 only monitor extensions whose name is in the <replaceable>ext</replaceable> : delimited 
102                                                 list.</para>
103                                         </option>
104                                         <option name="E">
105                                                 <para>Exit when the spied-on channel hangs up.</para>
106                                         </option>
107                                         <option name="g">
108                                                 <argument name="grp" required="true">
109                                                         <para>Only spy on channels in which one or more of the groups
110                                                         listed in <replaceable>grp</replaceable> matches one or more groups from the
111                                                         <variable>SPYGROUP</variable> variable set on the channel to be spied upon.</para>
112                                                 </argument>
113                                                 <note><para>both <replaceable>grp</replaceable> and <variable>SPYGROUP</variable> can contain 
114                                                 either a single group or a colon-delimited list of groups, such
115                                                 as <literal>sales:support:accounting</literal>.</para></note>
116                                         </option>
117                                         <option name="n" argsep="@">
118                                                 <para>Say the name of the person being spied on if that person has recorded
119                                                 his/her name. If a context is specified, then that voicemail context will
120                                                 be searched when retrieving the name, otherwise the <literal>default</literal> context
121                                                 be used when searching for the name (i.e. if SIP/1000 is the channel being
122                                                 spied on and no mailbox is specified, then <literal>1000</literal> will be used when searching
123                                                 for the name).</para>
124                                                 <argument name="mailbox" />
125                                                 <argument name="context" />
126                                         </option>
127                                         <option name="o">
128                                                 <para>Only listen to audio coming from this channel.</para>
129                                         </option>
130                                         <option name="q">
131                                                 <para>Don't play a beep when beginning to spy on a channel, or speak the
132                                                 selected channel name.</para>
133                                         </option>
134                                         <option name="r">
135                                                 <para>Record the session to the monitor spool directory. An optional base for the filename 
136                                                 may be specified. The default is <literal>chanspy</literal>.</para>
137                                                 <argument name="basename" />
138                                         </option>
139                                         <option name="s">
140                                                 <para>Skip the playback of the channel type (i.e. SIP, IAX, etc) when
141                                                 speaking the selected channel name.</para>
142                                         </option>
143                                         <option name="S">
144                                                 <para>Stop when no more channels are left to spy on.</para>
145                                         </option>
146                                         <option name="v">
147                                                 <argument name="value" />
148                                                 <para>Adjust the initial volume in the range from <literal>-4</literal> 
149                                                 to <literal>4</literal>. A negative value refers to a quieter setting.</para>
150                                         </option>
151                                         <option name="w">
152                                                 <para>Enable <literal>whisper</literal> mode, so the spying channel can talk to
153                                                 the spied-on channel.</para>
154                                         </option>
155                                         <option name="W">
156                                                 <para>Enable <literal>private whisper</literal> mode, so the spying channel can
157                                                 talk to the spied-on channel but cannot listen to that channel.</para>
158                                         </option>
159                                         <option name="x">
160                                                 <argument name="digit" required="true">
161                                                         <para>Specify a DTMF digit that can be used to exit the application.</para>
162                                                 </argument>
163                                         </option>
164                                         <option name="X">
165                                                 <para>Allow the user to exit ChanSpy to a valid single digit
166                                                 numeric extension in the current context or the context
167                                                 specified by the <variable>SPY_EXIT_CONTEXT</variable> channel variable. The
168                                                 name of the last channel that was spied on will be stored
169                                                 in the <variable>SPY_CHANNEL</variable> variable.</para>
170                                         </option>
171                                 </optionlist>           
172                         </parameter>
173                 </syntax>
174                 <description>
175                         <para>This application is used to listen to the audio from an Asterisk channel. This includes the audio 
176                         coming in and out of the channel being spied on. If the <literal>chanprefix</literal> parameter is specified,
177                         only channels beginning with this string will be spied upon.</para>
178                         <para>While spying, the following actions may be performed:</para>
179                         <para> - Dialing <literal>#</literal> cycles the volume level.</para>
180                         <para> - Dialing <literal>*</literal> will stop spying and look for another channel to spy on.</para>
181                         <para> - Dialing a series of digits followed by <literal>#</literal> builds a channel name to append
182                         to 'chanprefix'. For example, executing ChanSpy(Agent) and then dialing the digits '1234#' 
183                         while spying will begin spying on the channel 'Agent/1234'. Note that this feature will be overridden if the 'd' option
184                         is used</para>
185                         <note><para>The <replaceable>X</replaceable> option supersedes the three features above in that if a valid
186                         single digit extension exists in the correct context ChanSpy will exit to it.
187                         This also disables choosing a channel based on <literal>chanprefix</literal> and a digit sequence.</para></note>
188                 </description>
189                 <see-also>
190                         <ref type="application">ExtenSpy</ref>
191                 </see-also>
192         </application>
193         <application name="ExtenSpy" language="en_US">
194                 <synopsis>
195                         Listen to a channel, and optionally whisper into it.
196                 </synopsis>
197                 <syntax>
198                         <parameter name="exten" required="true" argsep="@">
199                                 <argument name="exten" required="true">
200                                         <para>Specify extension.</para>
201                                 </argument>
202                                 <argument name="context">
203                                         <para>Optionally specify a context, defaults to <literal>default</literal>.</para>
204                                 </argument>
205                         </parameter>
206                         <parameter name="options">
207                                 <optionlist>
208                                         <option name="b">
209                                                 <para>Only spy on channels involved in a bridged call.</para>
210                                         </option>
211                                         <option name="B">
212                                                 <para>Instead of whispering on a single channel barge in on both
213                                                 channels involved in the call.</para>
214                                         </option>
215                                         <option name="c">
216                                                 <argument name="digit" required="true">
217                                                         <para>Specify a DTMF digit that can be used to spy on the next available channel.</para>
218                                                 </argument>
219                                         </option>
220                                         <option name="d">
221                                                 <para>Override the typical numeric DTMF functionality and instead
222                                                 use DTMF to switch between spy modes.</para>
223                                                 <enumlist>
224                                                         <enum name="4">
225                                                                 <para>spy mode</para>
226                                                         </enum>
227                                                         <enum name="5">
228                                                                 <para>whisper mode</para>
229                                                         </enum>
230                                                         <enum name="6">
231                                                                 <para>barge mode</para>
232                                                         </enum>
233                                                 </enumlist>
234                                         </option>
235                                         <option name="e">
236                                                 <argument name="ext" required="true" />
237                                                 <para>Enable <emphasis>enforced</emphasis> mode, so the spying channel can
238                                                 only monitor extensions whose name is in the <replaceable>ext</replaceable> : delimited 
239                                                 list.</para>
240                                         </option>
241                                         <option name="E">
242                                                 <para>Exit when the spied-on channel hangs up.</para>
243                                         </option>
244                                         <option name="g">
245                                                 <argument name="grp" required="true">
246                                                         <para>Only spy on channels in which one or more of the groups
247                                                         listed in <replaceable>grp</replaceable> matches one or more groups from the
248                                                         <variable>SPYGROUP</variable> variable set on the channel to be spied upon.</para>
249                                                 </argument>
250                                                 <note><para>both <replaceable>grp</replaceable> and <variable>SPYGROUP</variable> can contain 
251                                                 either a single group or a colon-delimited list of groups, such
252                                                 as <literal>sales:support:accounting</literal>.</para></note>
253                                         </option>
254                                         <option name="n" argsep="@">
255                                                 <para>Say the name of the person being spied on if that person has recorded
256                                                 his/her name. If a context is specified, then that voicemail context will
257                                                 be searched when retrieving the name, otherwise the <literal>default</literal> context
258                                                 be used when searching for the name (i.e. if SIP/1000 is the channel being
259                                                 spied on and no mailbox is specified, then <literal>1000</literal> will be used when searching
260                                                 for the name).</para>
261                                                 <argument name="mailbox" />
262                                                 <argument name="context" />
263                                         </option>
264                                         <option name="o">
265                                                 <para>Only listen to audio coming from this channel.</para>
266                                         </option>
267                                         <option name="q">
268                                                 <para>Don't play a beep when beginning to spy on a channel, or speak the
269                                                 selected channel name.</para>
270                                         </option>
271                                         <option name="r">
272                                                 <para>Record the session to the monitor spool directory. An optional base for the filename 
273                                                 may be specified. The default is <literal>chanspy</literal>.</para>
274                                                 <argument name="basename" />
275                                         </option>
276                                         <option name="s">
277                                                 <para>Skip the playback of the channel type (i.e. SIP, IAX, etc) when
278                                                 speaking the selected channel name.</para>
279                                         </option>
280                                         <option name="S">
281                                                 <para>Stop when there are no more extensions left to spy on.</para>
282                                         </option>
283                                         <option name="v">
284                                                 <argument name="value" />
285                                                 <para>Adjust the initial volume in the range from <literal>-4</literal> 
286                                                 to <literal>4</literal>. A negative value refers to a quieter setting.</para>
287                                         </option>
288                                         <option name="w">
289                                                 <para>Enable <literal>whisper</literal> mode, so the spying channel can talk to
290                                                 the spied-on channel.</para>
291                                         </option>
292                                         <option name="W">
293                                                 <para>Enable <literal>private whisper</literal> mode, so the spying channel can
294                                                 talk to the spied-on channel but cannot listen to that channel.</para>
295                                         </option>
296                                         <option name="x">
297                                                 <argument name="digit" required="true">
298                                                         <para>Specify a DTMF digit that can be used to exit the application.</para>
299                                                 </argument>
300                                         </option>
301                                         <option name="X">
302                                                 <para>Allow the user to exit ChanSpy to a valid single digit
303                                                 numeric extension in the current context or the context
304                                                 specified by the <variable>SPY_EXIT_CONTEXT</variable> channel variable. The
305                                                 name of the last channel that was spied on will be stored
306                                                 in the <variable>SPY_CHANNEL</variable> variable.</para>
307                                         </option>
308                                 </optionlist>   
309                         </parameter>
310                 </syntax>
311                 <description>
312                         <para>This application is used to listen to the audio from an Asterisk channel. This includes 
313                         the audio coming in and out of the channel being spied on. Only channels created by outgoing calls for the
314                         specified extension will be selected for spying. If the optional context is not supplied, 
315                         the current channel's context will be used.</para>
316                         <para>While spying, the following actions may be performed:</para>
317                         <para> - Dialing <literal>#</literal> cycles the volume level.</para>
318                         <para> - Dialing <literal>*</literal> will stop spying and look for another channel to spy on.</para>
319                         <note><para>The <replaceable>X</replaceable> option supersedes the three features above in that if a valid
320                         single digit extension exists in the correct context ChanSpy will exit to it.
321                         This also disables choosing a channel based on <literal>chanprefix</literal> and a digit sequence.</para></note>
322                 </description>
323                 <see-also>
324                         <ref type="application">ChanSpy</ref>
325                 </see-also>
326         </application>
327         
328         <application name="DAHDIScan" language="en_US">
329                 <synopsis>
330                         Scan DAHDI channels to monitor calls.
331                 </synopsis>
332                 <syntax>
333                         <parameter name="group">
334                                 <para>Limit scanning to a channel <replaceable>group</replaceable> by setting this option.</para>
335                         </parameter>
336                 </syntax>
337                 <description>
338                         <para>Allows a call center manager to monitor DAHDI channels in a
339                         convenient way.  Use <literal>#</literal> to select the next channel and use <literal>*</literal> to exit.</para>
340                 </description>
341         </application>
342  ***/
343
344 static const char app_chan[] = "ChanSpy";
345
346 static const char app_ext[] = "ExtenSpy";
347
348 static const char app_dahdiscan[] = "DAHDIScan";
349
350 enum {
351         OPTION_QUIET             = (1 << 0),    /* Quiet, no announcement */
352         OPTION_BRIDGED           = (1 << 1),    /* Only look at bridged calls */
353         OPTION_VOLUME            = (1 << 2),    /* Specify initial volume */
354         OPTION_GROUP             = (1 << 3),    /* Only look at channels in group */
355         OPTION_RECORD            = (1 << 4),
356         OPTION_WHISPER           = (1 << 5),
357         OPTION_PRIVATE           = (1 << 6),    /* Private Whisper mode */
358         OPTION_READONLY          = (1 << 7),    /* Don't mix the two channels */
359         OPTION_EXIT              = (1 << 8),    /* Exit to a valid single digit extension */
360         OPTION_ENFORCED          = (1 << 9),    /* Enforced mode */
361         OPTION_NOTECH            = (1 << 10),   /* Skip technology name playback */
362         OPTION_BARGE             = (1 << 11),   /* Barge mode (whisper to both channels) */
363         OPTION_NAME              = (1 << 12),   /* Say the name of the person on whom we will spy */
364         OPTION_DTMF_SWITCH_MODES = (1 << 13),   /* Allow numeric DTMF to switch between chanspy modes */
365         OPTION_DTMF_EXIT         = (1 << 14),   /* Set DTMF to exit, added for DAHDIScan integration */
366         OPTION_DTMF_CYCLE        = (1 << 15),   /* Custom DTMF for cycling next avaliable channel, (default is '*') */
367         OPTION_DAHDI_SCAN        = (1 << 16),   /* Scan groups in DAHDIScan mode */
368         OPTION_STOP              = (1 << 17),
369         OPTION_EXITONHANGUP      = (1 << 18),   /* Hang up when the spied-on channel hangs up. */
370 };
371
372 enum {
373         OPT_ARG_VOLUME = 0,
374         OPT_ARG_GROUP,
375         OPT_ARG_RECORD,
376         OPT_ARG_ENFORCED,
377         OPT_ARG_NAME,
378         OPT_ARG_EXIT,
379         OPT_ARG_CYCLE,
380         OPT_ARG_ARRAY_SIZE,
381 };
382
383 AST_APP_OPTIONS(spy_opts, {
384         AST_APP_OPTION('b', OPTION_BRIDGED),
385         AST_APP_OPTION('B', OPTION_BARGE),
386         AST_APP_OPTION_ARG('c', OPTION_DTMF_CYCLE, OPT_ARG_CYCLE),
387         AST_APP_OPTION('d', OPTION_DTMF_SWITCH_MODES),
388         AST_APP_OPTION_ARG('e', OPTION_ENFORCED, OPT_ARG_ENFORCED),
389         AST_APP_OPTION('E', OPTION_EXITONHANGUP),
390         AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP),
391         AST_APP_OPTION_ARG('n', OPTION_NAME, OPT_ARG_NAME),
392         AST_APP_OPTION('o', OPTION_READONLY),
393         AST_APP_OPTION('q', OPTION_QUIET),
394         AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
395         AST_APP_OPTION('s', OPTION_NOTECH),
396         AST_APP_OPTION('S', OPTION_STOP),
397         AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
398         AST_APP_OPTION('w', OPTION_WHISPER),
399         AST_APP_OPTION('W', OPTION_PRIVATE),
400         AST_APP_OPTION_ARG('x', OPTION_DTMF_EXIT, OPT_ARG_EXIT),
401         AST_APP_OPTION('X', OPTION_EXIT),
402 });
403
404 struct chanspy_translation_helper {
405         /* spy data */
406         struct ast_audiohook spy_audiohook;
407         struct ast_audiohook whisper_audiohook;
408         struct ast_audiohook bridge_whisper_audiohook;
409         int fd;
410         int volfactor;
411         struct ast_flags flags;
412 };
413
414 struct spy_dtmf_options {
415         char exit;
416         char cycle;
417         char volume;
418 };
419
420 static void *spy_alloc(struct ast_channel *chan, void *data)
421 {
422         /* just store the data pointer in the channel structure */
423         return data;
424 }
425
426 static void spy_release(struct ast_channel *chan, void *data)
427 {
428         /* nothing to do */
429 }
430
431 static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
432 {
433         struct chanspy_translation_helper *csth = data;
434         struct ast_frame *f, *cur;
435         struct ast_format format_slin;
436
437         ast_format_set(&format_slin, AST_FORMAT_SLINEAR, 0);
438
439         ast_audiohook_lock(&csth->spy_audiohook);
440         if (csth->spy_audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
441                 /* Channel is already gone more than likely */
442                 ast_audiohook_unlock(&csth->spy_audiohook);
443                 return -1;
444         }
445
446         if (ast_test_flag(&csth->flags, OPTION_READONLY)) {
447                 /* Option 'o' was set, so don't mix channel audio */
448                 f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_READ, &format_slin);
449         } else {
450                 f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, &format_slin);
451         }
452
453         ast_audiohook_unlock(&csth->spy_audiohook);
454
455         if (!f)
456                 return 0;
457
458         for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
459                 if (ast_write(chan, cur)) {
460                         ast_frfree(f);
461                         return -1;
462                 }
463
464                 if (csth->fd) {
465                         if (write(csth->fd, cur->data.ptr, cur->datalen) < 0) {
466                                 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
467                         }
468                 }
469         }
470
471         ast_frfree(f);
472
473         return 0;
474 }
475
476 static struct ast_generator spygen = {
477         .alloc = spy_alloc,
478         .release = spy_release,
479         .generate = spy_generate,
480 };
481
482 static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook)
483 {
484         int res = 0;
485         struct ast_channel *peer = NULL;
486
487         ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));
488
489         ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC | AST_AUDIOHOOK_SMALL_QUEUE);
490         res = ast_audiohook_attach(autochan->chan, audiohook);
491
492         if (!res && ast_test_flag(ast_channel_flags(autochan->chan), AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(autochan->chan))) {
493                 ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
494         }
495         return res;
496 }
497
498 static void change_spy_mode(const char digit, struct ast_flags *flags)
499 {
500         if (digit == '4') {
501                 ast_clear_flag(flags, OPTION_WHISPER);
502                 ast_clear_flag(flags, OPTION_BARGE);
503         } else if (digit == '5') {
504                 ast_clear_flag(flags, OPTION_BARGE);
505                 ast_set_flag(flags, OPTION_WHISPER);
506         } else if (digit == '6') {
507                 ast_clear_flag(flags, OPTION_WHISPER);
508                 ast_set_flag(flags, OPTION_BARGE);
509         }
510 }
511
512 static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_autochan,
513         int *volfactor, int fd, struct spy_dtmf_options *user_options, struct ast_flags *flags,
514         char *exitcontext)
515 {
516         struct chanspy_translation_helper csth;
517         int running = 0, res, x = 0;
518         char inp[24] = {0};
519         char *name;
520         struct ast_frame *f;
521         struct ast_silence_generator *silgen = NULL;
522         struct ast_autochan *spyee_bridge_autochan = NULL;
523         const char *spyer_name;
524         struct ast_channel *chans[] = { chan, spyee_autochan->chan };
525
526         ast_channel_lock(chan);
527         spyer_name = ast_strdupa(ast_channel_name(chan));
528         ast_channel_unlock(chan);
529
530         /* We now hold the channel lock on spyee */
531
532         if (ast_check_hangup(chan) || ast_check_hangup(spyee_autochan->chan) ||
533                         ast_test_flag(ast_channel_flags(spyee_autochan->chan), AST_FLAG_ZOMBIE)) {
534                 return 0;
535         }
536
537         ast_channel_lock(spyee_autochan->chan);
538         name = ast_strdupa(ast_channel_name(spyee_autochan->chan));
539         ast_channel_unlock(spyee_autochan->chan);
540
541         ast_verb(2, "Spying on channel %s\n", name);
542         /*** DOCUMENTATION
543                 <managerEventInstance>
544                         <synopsis>Raised when a channel has started spying on another channel.</synopsis>
545                         <see-also>
546                                 <ref type="application">ChanSpy</ref>
547                                 <ref type="application">ExtenSpy</ref>
548                                 <ref type="managerEvent">ChanSpyStop</ref>
549                         </see-also>
550                 </managerEventInstance>
551         ***/
552         ast_manager_event_multichan(EVENT_FLAG_CALL, "ChanSpyStart", 2, chans,
553                         "SpyerChannel: %s\r\n"
554                         "SpyeeChannel: %s\r\n",
555                         spyer_name, name);
556
557         memset(&csth, 0, sizeof(csth));
558         ast_copy_flags(&csth.flags, flags, AST_FLAGS_ALL);
559
560         /* This is the audiohook which gives us the audio off the channel we are
561            spying on.
562         */
563         ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy", 0);
564
565         if (start_spying(spyee_autochan, spyer_name, &csth.spy_audiohook)) {
566                 ast_audiohook_destroy(&csth.spy_audiohook);
567                 return 0;
568         }
569
570         if (ast_test_flag(flags, OPTION_WHISPER | OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
571                 /* This audiohook will let us inject audio from our channel into the
572                    channel we are currently spying on.
573                 */
574                 ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy", 0);
575
576                 if (start_spying(spyee_autochan, spyer_name, &csth.whisper_audiohook)) {
577                         ast_log(LOG_WARNING, "Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", name);
578                 }
579         }
580
581         if (ast_test_flag(flags, OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
582                 /* And this hook lets us inject audio into the channel that the spied on
583                    channel is currently bridged with.
584                 */
585                 ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy", 0);
586
587                 if ((spyee_bridge_autochan = ast_autochan_setup(ast_bridged_channel(spyee_autochan->chan)))) {
588                         ast_channel_lock(spyee_bridge_autochan->chan);
589                         if (start_spying(spyee_bridge_autochan, spyer_name, &csth.bridge_whisper_audiohook)) {
590                                 ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee %s. Barge mode disabled!\n", name);
591                         }
592                         ast_channel_unlock(spyee_bridge_autochan->chan);
593                 }
594         }
595
596         ast_channel_lock(chan);
597         ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
598         ast_channel_unlock(chan);
599
600         csth.volfactor = *volfactor;
601
602         if (csth.volfactor) {
603                 csth.spy_audiohook.options.read_volume = csth.volfactor;
604                 csth.spy_audiohook.options.write_volume = csth.volfactor;
605         }
606
607         csth.fd = fd;
608
609         if (ast_test_flag(flags, OPTION_PRIVATE))
610                 silgen = ast_channel_start_silence_generator(chan);
611         else
612                 ast_activate_generator(chan, &spygen, &csth);
613
614         /* We can no longer rely on 'spyee' being an actual channel;
615            it can be hung up and freed out from under us. However, the
616            channel destructor will put NULL into our csth.spy.chan
617            field when that happens, so that is our signal that the spyee
618            channel has gone away.
619         */
620
621         /* Note: it is very important that the ast_waitfor() be the first
622            condition in this expression, so that if we wait for some period
623            of time before receiving a frame from our spying channel, we check
624            for hangup on the spied-on channel _after_ knowing that a frame
625            has arrived, since the spied-on channel could have gone away while
626            we were waiting
627         */
628         while (ast_waitfor(chan, -1) > -1 && csth.spy_audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
629                 if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
630                         running = -1;
631                         break;
632                 }
633
634                 if (ast_test_flag(flags, OPTION_BARGE) && f->frametype == AST_FRAME_VOICE) {
635                         ast_audiohook_lock(&csth.whisper_audiohook);
636                         ast_audiohook_lock(&csth.bridge_whisper_audiohook);
637                         ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
638                         ast_audiohook_write_frame(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
639                         ast_audiohook_unlock(&csth.whisper_audiohook);
640                         ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
641                         ast_frfree(f);
642                         continue;
643                 } else if (ast_test_flag(flags, OPTION_WHISPER) && f->frametype == AST_FRAME_VOICE) {
644                         ast_audiohook_lock(&csth.whisper_audiohook);
645                         ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
646                         ast_audiohook_unlock(&csth.whisper_audiohook);
647                         ast_frfree(f);
648                         continue;
649                 }
650                 
651                 res = (f->frametype == AST_FRAME_DTMF) ? f->subclass.integer : 0;
652                 ast_frfree(f);
653                 if (!res)
654                         continue;
655
656                 if (x == sizeof(inp))
657                         x = 0;
658
659                 if (res < 0) {
660                         running = -1;
661                         break;
662                 }
663
664                 if (ast_test_flag(flags, OPTION_EXIT)) {
665                         char tmp[2];
666                         tmp[0] = res;
667                         tmp[1] = '\0';
668                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
669                                 ast_debug(1, "Got DTMF %c, goto context %s\n", tmp[0], exitcontext);
670                                 pbx_builtin_setvar_helper(chan, "SPY_CHANNEL", name);
671                                 running = -2;
672                                 break;
673                         } else {
674                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
675                         }
676                 } else if (res >= '0' && res <= '9') {
677                         if (ast_test_flag(flags, OPTION_DTMF_SWITCH_MODES)) {
678                                 change_spy_mode(res, flags);
679                         } else {
680                                 inp[x++] = res;
681                         }
682                 }
683
684                 if (res == user_options->cycle) {
685                         running = 0;
686                         break;
687                 } else if (res == user_options->exit) {
688                         running = -2;
689                         break;
690                 } else if (res == user_options->volume) {
691                         if (!ast_strlen_zero(inp)) {
692                                 running = atoi(inp);
693                                 break;
694                         }
695
696                         (*volfactor)++;
697                         if (*volfactor > 4)
698                                 *volfactor = -4;
699                         ast_verb(3, "Setting spy volume on %s to %d\n", ast_channel_name(chan), *volfactor);
700
701                         csth.volfactor = *volfactor;
702                         csth.spy_audiohook.options.read_volume = csth.volfactor;
703                         csth.spy_audiohook.options.write_volume = csth.volfactor;
704                 }
705         }
706
707         if (ast_test_flag(flags, OPTION_PRIVATE))
708                 ast_channel_stop_silence_generator(chan, silgen);
709         else
710                 ast_deactivate_generator(chan);
711
712         ast_channel_lock(chan);
713         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
714         ast_channel_unlock(chan);
715
716         if (ast_test_flag(flags, OPTION_WHISPER | OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
717                 ast_audiohook_lock(&csth.whisper_audiohook);
718                 ast_audiohook_detach(&csth.whisper_audiohook);
719                 ast_audiohook_unlock(&csth.whisper_audiohook);
720                 ast_audiohook_destroy(&csth.whisper_audiohook);
721         }
722
723         if (ast_test_flag(flags, OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
724                 ast_audiohook_lock(&csth.bridge_whisper_audiohook);
725                 ast_audiohook_detach(&csth.bridge_whisper_audiohook);
726                 ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
727                 ast_audiohook_destroy(&csth.bridge_whisper_audiohook);
728         }
729
730         ast_audiohook_lock(&csth.spy_audiohook);
731         ast_audiohook_detach(&csth.spy_audiohook);
732         ast_audiohook_unlock(&csth.spy_audiohook);
733         ast_audiohook_destroy(&csth.spy_audiohook);
734
735         if (spyee_bridge_autochan) {
736                 ast_autochan_destroy(spyee_bridge_autochan);
737         }
738
739         ast_verb(2, "Done Spying on channel %s\n", name);
740         /*** DOCUMENTATION
741                 <managerEventInstance>
742                         <synopsis>Raised when a channel has stopped spying on another channel.</synopsis>
743                         <see-also>
744                                 <ref type="managerEvent">ChanSpyStart</ref>
745                         </see-also>
746                 </managerEventInstance>
747         ***/
748         ast_manager_event(chan, EVENT_FLAG_CALL, "ChanSpyStop", "SpyeeChannel: %s\r\n", name);
749
750         return running;
751 }
752
753 static struct ast_autochan *next_channel(struct ast_channel_iterator *iter,
754                 struct ast_autochan *autochan, struct ast_channel *chan)
755 {
756         struct ast_channel *next;
757         struct ast_autochan *autochan_store;
758         const size_t pseudo_len = strlen("DAHDI/pseudo");
759
760         if (!iter) {
761                 return NULL;
762         }
763
764         for (; (next = ast_channel_iterator_next(iter)); ast_channel_unref(next)) {
765                 if (!strncmp(ast_channel_name(next), "DAHDI/pseudo", pseudo_len)
766                         || next == chan) {
767                         continue;
768                 }
769
770                 autochan_store = ast_autochan_setup(next);
771                 ast_channel_unref(next);
772
773                 return autochan_store;
774         }
775         return NULL;
776 }
777
778 static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
779         int volfactor, const int fd, struct spy_dtmf_options *user_options,
780         const char *mygroup, const char *myenforced, const char *spec, const char *exten,
781         const char *context, const char *mailbox, const char *name_context)
782 {
783         char nameprefix[AST_NAME_STRLEN];
784         char exitcontext[AST_MAX_CONTEXT] = "";
785         signed char zero_volume = 0;
786         int waitms;
787         int res;
788         int num_spyed_upon = 1;
789         struct ast_channel_iterator *iter = NULL;
790
791         if (ast_test_flag(flags, OPTION_EXIT)) {
792                 const char *c;
793                 ast_channel_lock(chan);
794                 if ((c = pbx_builtin_getvar_helper(chan, "SPY_EXIT_CONTEXT"))) {
795                         ast_copy_string(exitcontext, c, sizeof(exitcontext));
796                 } else if (!ast_strlen_zero(ast_channel_macrocontext(chan))) {
797                         ast_copy_string(exitcontext, ast_channel_macrocontext(chan), sizeof(exitcontext));
798                 } else {
799                         ast_copy_string(exitcontext, ast_channel_context(chan), sizeof(exitcontext));
800                 }
801                 ast_channel_unlock(chan);
802         }
803
804         if (ast_channel_state(chan) != AST_STATE_UP)
805                 ast_answer(chan);
806
807         ast_set_flag(ast_channel_flags(chan), AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
808
809         waitms = 100;
810
811         for (;;) {
812                 struct ast_autochan *autochan = NULL, *next_autochan = NULL;
813                 struct ast_channel *prev = NULL;
814
815                 if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) {
816                         res = ast_streamfile(chan, "beep", ast_channel_language(chan));
817                         if (!res)
818                                 res = ast_waitstream(chan, "");
819                         else if (res < 0) {
820                                 ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
821                                 break;
822                         }
823                         if (!ast_strlen_zero(exitcontext)) {
824                                 char tmp[2];
825                                 tmp[0] = res;
826                                 tmp[1] = '\0';
827                                 if (!ast_goto_if_exists(chan, exitcontext, tmp, 1))
828                                         goto exit;
829                                 else
830                                         ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
831                         }
832                 }
833
834                 /* Set up the iterator we'll be using during this call */
835                 if (!ast_strlen_zero(spec)) {
836                         iter = ast_channel_iterator_by_name_new(spec, strlen(spec));
837                 } else if (!ast_strlen_zero(exten)) {
838                         iter = ast_channel_iterator_by_exten_new(exten, context);
839                 } else {
840                         iter = ast_channel_iterator_all_new();
841                 }
842
843                 if (!iter) {
844                         res = -1;
845                         goto exit;
846                 }
847
848                 res = ast_waitfordigit(chan, waitms);
849                 if (res < 0) {
850                         iter = ast_channel_iterator_destroy(iter);
851                         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
852                         break;
853                 }
854                 if (!ast_strlen_zero(exitcontext)) {
855                         char tmp[2];
856                         tmp[0] = res;
857                         tmp[1] = '\0';
858                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
859                                 iter = ast_channel_iterator_destroy(iter);
860                                 goto exit;
861                         } else {
862                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
863                         }
864                 }
865
866                 /* reset for the next loop around, unless overridden later */
867                 waitms = 100;
868                 num_spyed_upon = 0;
869
870                 for (autochan = next_channel(iter, autochan, chan);
871                      autochan;
872                          prev = autochan->chan, ast_autochan_destroy(autochan),
873                      autochan = next_autochan ? next_autochan : 
874                                 next_channel(iter, autochan, chan), next_autochan = NULL) {
875                         int igrp = !mygroup;
876                         int ienf = !myenforced;
877
878                         if (autochan->chan == prev) {
879                                 ast_autochan_destroy(autochan);
880                                 break;
881                         }
882
883                         if (ast_check_hangup(chan)) {
884                                 ast_autochan_destroy(autochan);
885                                 break;
886                         }
887
888                         if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(autochan->chan)) {
889                                 continue;
890                         }
891
892                         if (ast_check_hangup(autochan->chan) || ast_test_flag(ast_channel_flags(autochan->chan), AST_FLAG_SPYING)) {
893                                 continue;
894                         }
895
896                         if (mygroup) {
897                                 int num_groups = 0;
898                                 int num_mygroups = 0;
899                                 char dup_group[512];
900                                 char dup_mygroup[512];
901                                 char *groups[NUM_SPYGROUPS];
902                                 char *mygroups[NUM_SPYGROUPS];
903                                 const char *group = NULL;
904                                 int x;
905                                 int y;
906                                 ast_copy_string(dup_mygroup, mygroup, sizeof(dup_mygroup));
907                                 num_mygroups = ast_app_separate_args(dup_mygroup, ':', mygroups,
908                                         ARRAY_LEN(mygroups));
909
910                                 /* Before dahdi scan was part of chanspy, it would use the "GROUP" variable 
911                                  * rather than "SPYGROUP", this check is done to preserve expected behavior */
912                                 if (ast_test_flag(flags, OPTION_DAHDI_SCAN)) {
913                                         group = pbx_builtin_getvar_helper(autochan->chan, "GROUP");
914                                 } else {
915                                         group = pbx_builtin_getvar_helper(autochan->chan, "SPYGROUP");
916                                 }
917
918                                 if (!ast_strlen_zero(group)) {
919                                         ast_copy_string(dup_group, group, sizeof(dup_group));
920                                         num_groups = ast_app_separate_args(dup_group, ':', groups,
921                                                 ARRAY_LEN(groups));
922                                 }
923
924                                 for (y = 0; y < num_mygroups; y++) {
925                                         for (x = 0; x < num_groups; x++) {
926                                                 if (!strcmp(mygroups[y], groups[x])) {
927                                                         igrp = 1;
928                                                         break;
929                                                 }
930                                         }
931                                 }
932                         }
933
934                         if (!igrp) {
935                                 continue;
936                         }
937                         if (myenforced) {
938                                 char ext[AST_CHANNEL_NAME + 3];
939                                 char buffer[512];
940                                 char *end;
941
942                                 snprintf(buffer, sizeof(buffer) - 1, ":%s:", myenforced);
943
944                                 ast_copy_string(ext + 1, ast_channel_name(autochan->chan), sizeof(ext) - 1);
945                                 if ((end = strchr(ext, '-'))) {
946                                         *end++ = ':';
947                                         *end = '\0';
948                                 }
949
950                                 ext[0] = ':';
951
952                                 if (strcasestr(buffer, ext)) {
953                                         ienf = 1;
954                                 }
955                         }
956
957                         if (!ienf) {
958                                 continue;
959                         }
960
961                         if (!ast_test_flag(flags, OPTION_QUIET)) {
962                                 char peer_name[AST_NAME_STRLEN + 5];
963                                 char *ptr, *s;
964
965                                 strcpy(peer_name, "spy-");
966                                 strncat(peer_name, ast_channel_name(autochan->chan), AST_NAME_STRLEN - 4 - 1);
967                                 if ((ptr = strchr(peer_name, '/'))) {
968                                         *ptr++ = '\0';
969                                         for (s = peer_name; s < ptr; s++) {
970                                                 *s = tolower(*s);
971                                         }
972                                         if ((s = strchr(ptr, '-'))) {
973                                                 *s = '\0';
974                                         }
975                                 }
976
977                                 if (ast_test_flag(flags, OPTION_NAME)) {
978                                         const char *local_context = S_OR(name_context, "default");
979                                         const char *local_mailbox = S_OR(mailbox, ptr);
980                                         if (local_mailbox) {
981                                                 res = ast_app_sayname(chan, local_mailbox, local_context);
982                                         } else {
983                                                 res = -1;
984                                         }
985                                 }
986                                 if (!ast_test_flag(flags, OPTION_NAME) || res < 0) {
987                                         int num;
988                                         if (!ast_test_flag(flags, OPTION_NOTECH)) {
989                                                 if (ast_fileexists(peer_name, NULL, NULL) > 0) {
990                                                         res = ast_streamfile(chan, peer_name, ast_channel_language(chan));
991                                                         if (!res) {
992                                                                 res = ast_waitstream(chan, "");
993                                                         }
994                                                         if (res) {
995                                                                 ast_autochan_destroy(autochan);
996                                                                 break;
997                                                         }
998                                                 } else {
999                                                         res = ast_say_character_str(chan, peer_name, "", ast_channel_language(chan));
1000                                                 }
1001                                         }
1002                                         if (ptr && (num = atoi(ptr))) {
1003                                                 ast_say_digits(chan, num, "", ast_channel_language(chan));
1004                                         }
1005                                 }
1006                         }
1007
1008                         res = channel_spy(chan, autochan, &volfactor, fd, user_options, flags, exitcontext);
1009                         num_spyed_upon++;
1010
1011                         if (res == -1) {
1012                                 ast_autochan_destroy(autochan);
1013                                 iter = ast_channel_iterator_destroy(iter);
1014                                 goto exit;
1015                         } else if (res == -2) {
1016                                 res = 0;
1017                                 ast_autochan_destroy(autochan);
1018                                 iter = ast_channel_iterator_destroy(iter);
1019                                 goto exit;
1020                         } else if (res > 1 && spec) {
1021                                 struct ast_channel *next;
1022
1023                                 snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);
1024
1025                                 if ((next = ast_channel_get_by_name_prefix(nameprefix, strlen(nameprefix)))) {
1026                                         next_autochan = ast_autochan_setup(next);
1027                                         next = ast_channel_unref(next);
1028                                 } else {
1029                                         /* stay on this channel, if it is still valid */
1030                                         if (!ast_check_hangup(autochan->chan)) {
1031                                                 next_autochan = ast_autochan_setup(autochan->chan);
1032                                         } else {
1033                                                 /* the channel is gone */
1034                                                 next_autochan = NULL;
1035                                         }
1036                                 }
1037                         } else if (res == 0 && ast_test_flag(flags, OPTION_EXITONHANGUP)) {
1038                                 ast_autochan_destroy(autochan);
1039                                 iter = ast_channel_iterator_destroy(iter);
1040                                 goto exit;
1041                         }
1042                 }
1043
1044                 iter = ast_channel_iterator_destroy(iter);
1045
1046                 if (res == -1 || ast_check_hangup(chan))
1047                         break;
1048                 if (ast_test_flag(flags, OPTION_STOP) && !next_autochan) {
1049                         break;
1050                 }
1051         }
1052 exit:
1053
1054         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
1055
1056         ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
1057
1058         return res;
1059 }
1060
1061 static int chanspy_exec(struct ast_channel *chan, const char *data)
1062 {
1063         char *myenforced = NULL;
1064         char *mygroup = NULL;
1065         char *recbase = NULL;
1066         int fd = 0;
1067         struct ast_flags flags;
1068         struct spy_dtmf_options user_options = {
1069                 .cycle = '*',
1070                 .volume = '#',
1071                 .exit = '\0',
1072         };
1073         struct ast_format oldwf;
1074         int volfactor = 0;
1075         int res;
1076         char *mailbox = NULL;
1077         char *name_context = NULL;
1078         AST_DECLARE_APP_ARGS(args,
1079                 AST_APP_ARG(spec);
1080                 AST_APP_ARG(options);
1081         );
1082         char *opts[OPT_ARG_ARRAY_SIZE];
1083         char *parse = ast_strdupa(data);
1084
1085         AST_STANDARD_APP_ARGS(args, parse);
1086         ast_format_clear(&oldwf);
1087
1088         if (args.spec && !strcmp(args.spec, "all"))
1089                 args.spec = NULL;
1090
1091         if (args.options) {
1092                 char tmp;
1093                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
1094                 if (ast_test_flag(&flags, OPTION_GROUP))
1095                         mygroup = opts[OPT_ARG_GROUP];
1096
1097                 if (ast_test_flag(&flags, OPTION_RECORD) &&
1098                         !(recbase = opts[OPT_ARG_RECORD]))
1099                         recbase = "chanspy";
1100
1101                 if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
1102                         tmp = opts[OPT_ARG_EXIT][0];
1103                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1104                                 user_options.exit = tmp;
1105                         } else {
1106                                 ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.\n");
1107                         }
1108                 }
1109
1110                 if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
1111                         tmp = opts[OPT_ARG_CYCLE][0];
1112                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1113                                 user_options.cycle = tmp;
1114                         } else {
1115                                 ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.\n");
1116                         }
1117                 }
1118
1119                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
1120                         int vol;
1121
1122                         if ((sscanf(opts[OPT_ARG_VOLUME], "%30d", &vol) != 1) || (vol > 4) || (vol < -4))
1123                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
1124                         else
1125                                 volfactor = vol;
1126                 }
1127
1128                 if (ast_test_flag(&flags, OPTION_PRIVATE))
1129                         ast_set_flag(&flags, OPTION_WHISPER);
1130
1131                 if (ast_test_flag(&flags, OPTION_ENFORCED))
1132                         myenforced = opts[OPT_ARG_ENFORCED];
1133
1134                 if (ast_test_flag(&flags, OPTION_NAME)) {
1135                         if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
1136                                 char *delimiter;
1137                                 if ((delimiter = strchr(opts[OPT_ARG_NAME], '@'))) {
1138                                         mailbox = opts[OPT_ARG_NAME];
1139                                         *delimiter++ = '\0';
1140                                         name_context = delimiter;
1141                                 } else {
1142                                         mailbox = opts[OPT_ARG_NAME];
1143                                 }
1144                         }
1145                 }
1146         } else {
1147                 ast_clear_flag(&flags, AST_FLAGS_ALL);
1148         }
1149
1150         ast_format_copy(&oldwf, ast_channel_writeformat(chan));
1151         if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
1152                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1153                 return -1;
1154         }
1155
1156         if (recbase) {
1157                 char filename[PATH_MAX];
1158
1159                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
1160                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
1161                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
1162                         fd = 0;
1163                 }
1164         }
1165
1166         res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, myenforced, args.spec, NULL, NULL, mailbox, name_context);
1167
1168         if (fd)
1169                 close(fd);
1170
1171         if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
1172                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1173
1174         if (ast_test_flag(&flags, OPTION_EXITONHANGUP)) {
1175                 ast_verb(3, "Stopped spying due to the spied-on channel hanging up.\n");
1176         }
1177
1178         return res;
1179 }
1180
1181 static int extenspy_exec(struct ast_channel *chan, const char *data)
1182 {
1183         char *ptr, *exten = NULL;
1184         char *mygroup = NULL;
1185         char *recbase = NULL;
1186         int fd = 0;
1187         struct ast_flags flags;
1188         struct spy_dtmf_options user_options = {
1189                 .cycle = '*',
1190                 .volume = '#',
1191                 .exit = '\0',
1192         };
1193         struct ast_format oldwf;
1194         int volfactor = 0;
1195         int res;
1196         char *mailbox = NULL;
1197         char *name_context = NULL;
1198         AST_DECLARE_APP_ARGS(args,
1199                 AST_APP_ARG(context);
1200                 AST_APP_ARG(options);
1201         );
1202         char *parse = ast_strdupa(data);
1203
1204         AST_STANDARD_APP_ARGS(args, parse);
1205         ast_format_clear(&oldwf);
1206
1207         if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
1208                 exten = args.context;
1209                 *ptr++ = '\0';
1210                 args.context = ptr;
1211         }
1212         if (ast_strlen_zero(args.context))
1213                 args.context = ast_strdupa(ast_channel_context(chan));
1214
1215         if (args.options) {
1216                 char *opts[OPT_ARG_ARRAY_SIZE];
1217                 char tmp;
1218
1219                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
1220                 if (ast_test_flag(&flags, OPTION_GROUP))
1221                         mygroup = opts[OPT_ARG_GROUP];
1222
1223                 if (ast_test_flag(&flags, OPTION_RECORD) &&
1224                         !(recbase = opts[OPT_ARG_RECORD]))
1225                         recbase = "chanspy";
1226
1227                 if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
1228                         tmp = opts[OPT_ARG_EXIT][0];
1229                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1230                                 user_options.exit = tmp;
1231                         } else {
1232                                 ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.\n");
1233                         }
1234                 }
1235
1236                 if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
1237                         tmp = opts[OPT_ARG_CYCLE][0];
1238                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1239                                 user_options.cycle = tmp;
1240                         } else {
1241                                 ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.\n");
1242                         }
1243                 }
1244
1245                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
1246                         int vol;
1247
1248                         if ((sscanf(opts[OPT_ARG_VOLUME], "%30d", &vol) != 1) || (vol > 4) || (vol < -4))
1249                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
1250                         else
1251                                 volfactor = vol;
1252                 }
1253
1254                 if (ast_test_flag(&flags, OPTION_PRIVATE))
1255                         ast_set_flag(&flags, OPTION_WHISPER);
1256
1257                 if (ast_test_flag(&flags, OPTION_NAME)) {
1258                         if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
1259                                 char *delimiter;
1260                                 if ((delimiter = strchr(opts[OPT_ARG_NAME], '@'))) {
1261                                         mailbox = opts[OPT_ARG_NAME];
1262                                         *delimiter++ = '\0';
1263                                         name_context = delimiter;
1264                                 } else {
1265                                         mailbox = opts[OPT_ARG_NAME];
1266                                 }
1267                         }
1268                 }
1269
1270         } else {
1271                 /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
1272                 ast_clear_flag(&flags, AST_FLAGS_ALL);
1273         }
1274
1275         ast_format_copy(&oldwf, ast_channel_writeformat(chan));
1276         if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
1277                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1278                 return -1;
1279         }
1280
1281         if (recbase) {
1282                 char filename[PATH_MAX];
1283
1284                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
1285                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
1286                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
1287                         fd = 0;
1288                 }
1289         }
1290
1291
1292         res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, NULL, NULL, exten, args.context, mailbox, name_context);
1293
1294         if (fd)
1295                 close(fd);
1296
1297         if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
1298                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1299
1300         return res;
1301 }
1302
1303 static int dahdiscan_exec(struct ast_channel *chan, const char *data)
1304 {
1305         const char *spec = "DAHDI";
1306         struct ast_flags flags;
1307         struct spy_dtmf_options user_options = {
1308                 .cycle = '#',
1309                 .volume = '\0',
1310                 .exit = '*',
1311         };
1312         struct ast_format oldwf;
1313         int res;
1314         char *mygroup = NULL;
1315
1316         /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
1317         ast_clear_flag(&flags, AST_FLAGS_ALL);
1318         ast_format_clear(&oldwf);
1319         if (!ast_strlen_zero(data)) {
1320                 mygroup = ast_strdupa(data);
1321         }
1322         ast_set_flag(&flags, OPTION_DTMF_EXIT);
1323         ast_set_flag(&flags, OPTION_DTMF_CYCLE);
1324         ast_set_flag(&flags, OPTION_DAHDI_SCAN);
1325
1326         ast_format_copy(&oldwf, ast_channel_writeformat(chan));
1327         if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
1328                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1329                 return -1;
1330         }
1331
1332         res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);
1333
1334         if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
1335                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1336
1337         return res;
1338 }
1339
1340 static int unload_module(void)
1341 {
1342         int res = 0;
1343
1344         res |= ast_unregister_application(app_chan);
1345         res |= ast_unregister_application(app_ext);
1346         res |= ast_unregister_application(app_dahdiscan);
1347
1348         return res;
1349 }
1350
1351 static int load_module(void)
1352 {
1353         int res = 0;
1354
1355         res |= ast_register_application_xml(app_chan, chanspy_exec);
1356         res |= ast_register_application_xml(app_ext, extenspy_exec);
1357         res |= ast_register_application_xml(app_dahdiscan, dahdiscan_exec);
1358
1359         return res;
1360 }
1361
1362 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Listen to the audio of an active channel");