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