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