5806b997d7e68fc13131a7cb4bf2f47508bcd27f
[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         int res = 0;
502
503         ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));
504
505         ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC | AST_AUDIOHOOK_SMALL_QUEUE);
506         res = ast_audiohook_attach(autochan->chan, audiohook);
507
508         if (!res) {
509                 ast_channel_lock(autochan->chan);
510                 if (ast_channel_is_bridged(autochan->chan)) {
511                         ast_softhangup_nolock(autochan->chan, AST_SOFTHANGUP_UNBRIDGE);
512                 }
513                 ast_channel_unlock(autochan->chan);
514         }
515         return res;
516 }
517
518 static void change_spy_mode(const char digit, struct ast_flags *flags)
519 {
520         if (digit == '4') {
521                 ast_clear_flag(flags, OPTION_WHISPER);
522                 ast_clear_flag(flags, OPTION_BARGE);
523         } else if (digit == '5') {
524                 ast_clear_flag(flags, OPTION_BARGE);
525                 ast_set_flag(flags, OPTION_WHISPER);
526         } else if (digit == '6') {
527                 ast_clear_flag(flags, OPTION_WHISPER);
528                 ast_set_flag(flags, OPTION_BARGE);
529         }
530 }
531
532 static int pack_channel_into_message(struct ast_channel *chan, const char *role,
533                                                                          struct ast_multi_channel_blob *payload)
534 {
535         RAII_VAR(struct ast_channel_snapshot *, snapshot,
536                         ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)),
537                         ao2_cleanup);
538
539         if (!snapshot) {
540                 return -1;
541         }
542         ast_multi_channel_blob_add_channel(payload, role, snapshot);
543         return 0;
544 }
545
546 /*! \internal
547  * \brief Publish the chanspy message over Stasis-Core
548  * \param spyer The channel doing the spying
549  * \param spyee Who is being spied upon
550  * \start start If non-zero, the spying is starting. Otherwise, the spyer is
551  * finishing
552  */
553 static void publish_chanspy_message(struct ast_channel *spyer,
554                                                                         struct ast_channel *spyee,
555                                                                         int start)
556 {
557         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
558         RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
559         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
560         struct stasis_message_type *type = start ? ast_channel_chanspy_start_type(): ast_channel_chanspy_stop_type();
561
562         if (!spyer) {
563                 ast_log(AST_LOG_WARNING, "Attempt to publish ChanSpy message for NULL spyer channel\n");
564                 return;
565         }
566         blob = ast_json_null();
567         if (!blob || !type) {
568                 return;
569         }
570
571         payload = ast_multi_channel_blob_create(blob);
572         if (!payload) {
573                 return;
574         }
575
576         if (pack_channel_into_message(spyer, "spyer_channel", payload)) {
577                 return;
578         }
579
580         if (spyee) {
581                 if (pack_channel_into_message(spyee, "spyee_channel", payload)) {
582                         return;
583                 }
584         }
585
586         message = stasis_message_create(type, payload);
587         if (!message) {
588                 return;
589         }
590         stasis_publish(ast_channel_topic(spyer), message);
591 }
592
593 static int attach_barge(struct ast_autochan *spyee_autochan,
594         struct ast_autochan **spyee_bridge_autochan, struct ast_audiohook *bridge_whisper_audiohook,
595         const char *spyer_name, const char *name)
596 {
597         int retval = 0;
598         struct ast_autochan *internal_bridge_autochan;
599         RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(spyee_autochan->chan), ast_channel_cleanup);
600
601         if (!bridged) {
602                 return -1;
603         }
604
605         ast_audiohook_init(bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy", 0);
606
607         internal_bridge_autochan = ast_autochan_setup(bridged);
608         if (!internal_bridge_autochan) {
609                 return -1;
610         }
611
612         ast_channel_lock(internal_bridge_autochan->chan);
613         if (start_spying(internal_bridge_autochan, spyer_name, bridge_whisper_audiohook)) {
614                 ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee '%s'. Barge mode disabled.\n", name);
615                 retval = -1;
616         }
617         ast_channel_unlock(internal_bridge_autochan->chan);
618
619         *spyee_bridge_autochan = internal_bridge_autochan;
620
621         return retval;
622 }
623
624 static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_autochan,
625         int *volfactor, int fd, struct spy_dtmf_options *user_options, struct ast_flags *flags,
626         char *exitcontext)
627 {
628         struct chanspy_translation_helper csth;
629         int running = 0, bridge_connected = 0, res, x = 0;
630         char inp[24] = {0};
631         char *name;
632         struct ast_frame *f;
633         struct ast_silence_generator *silgen = NULL;
634         struct ast_autochan *spyee_bridge_autochan = NULL;
635         const char *spyer_name;
636
637         if (ast_check_hangup(chan) || ast_check_hangup(spyee_autochan->chan) ||
638                         ast_test_flag(ast_channel_flags(spyee_autochan->chan), AST_FLAG_ZOMBIE)) {
639                 return 0;
640         }
641
642         ast_channel_lock(chan);
643         spyer_name = ast_strdupa(ast_channel_name(chan));
644         ast_channel_unlock(chan);
645
646         ast_channel_lock(spyee_autochan->chan);
647         name = ast_strdupa(ast_channel_name(spyee_autochan->chan));
648         ast_channel_unlock(spyee_autochan->chan);
649
650         ast_verb(2, "Spying on channel %s\n", name);
651         publish_chanspy_message(chan, spyee_autochan->chan, 1);
652
653         memset(&csth, 0, sizeof(csth));
654         ast_copy_flags(&csth.flags, flags, AST_FLAGS_ALL);
655
656         /* This is the audiohook which gives us the audio off the channel we are
657            spying on.
658         */
659         ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy", 0);
660
661         if (start_spying(spyee_autochan, spyer_name, &csth.spy_audiohook)) {
662                 ast_audiohook_destroy(&csth.spy_audiohook);
663                 return 0;
664         }
665
666         if (ast_test_flag(flags, OPTION_WHISPER | OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
667                 /* This audiohook will let us inject audio from our channel into the
668                    channel we are currently spying on.
669                 */
670                 ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy", 0);
671
672                 if (start_spying(spyee_autochan, spyer_name, &csth.whisper_audiohook)) {
673                         ast_log(LOG_WARNING, "Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", name);
674                 }
675         }
676
677         ast_channel_lock(chan);
678         ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
679         ast_channel_unlock(chan);
680
681         csth.volfactor = *volfactor;
682
683         if (csth.volfactor) {
684                 csth.spy_audiohook.options.read_volume = csth.volfactor;
685                 csth.spy_audiohook.options.write_volume = csth.volfactor;
686         }
687
688         csth.fd = fd;
689
690         if (ast_test_flag(flags, OPTION_PRIVATE))
691                 silgen = ast_channel_start_silence_generator(chan);
692         else
693                 ast_activate_generator(chan, &spygen, &csth);
694
695         /* We can no longer rely on 'spyee' being an actual channel;
696            it can be hung up and freed out from under us. However, the
697            channel destructor will put NULL into our csth.spy.chan
698            field when that happens, so that is our signal that the spyee
699            channel has gone away.
700         */
701
702         /* Note: it is very important that the ast_waitfor() be the first
703            condition in this expression, so that if we wait for some period
704            of time before receiving a frame from our spying channel, we check
705            for hangup on the spied-on channel _after_ knowing that a frame
706            has arrived, since the spied-on channel could have gone away while
707            we were waiting
708         */
709         while (ast_waitfor(chan, -1) > -1 && csth.spy_audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
710                 if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
711                         running = -1;
712                         break;
713                 }
714
715                 if (ast_test_flag(flags, OPTION_BARGE) && f->frametype == AST_FRAME_VOICE) {
716                         /* This hook lets us inject audio into the channel that the spyee is currently
717                          * bridged with. If the spyee isn't bridged with anything yet, nothing will
718                          * be attached and we'll need to continue attempting to attach the barge
719                          * audio hook. */
720                         if (!bridge_connected && attach_barge(spyee_autochan, &spyee_bridge_autochan,
721                                         &csth.bridge_whisper_audiohook, spyer_name, name) == 0) {
722                                 bridge_connected = 1;
723                         }
724
725                         ast_audiohook_lock(&csth.whisper_audiohook);
726                         ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
727                         ast_audiohook_unlock(&csth.whisper_audiohook);
728
729                         if (bridge_connected) {
730                                 ast_audiohook_lock(&csth.bridge_whisper_audiohook);
731                                 ast_audiohook_write_frame(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
732                                 ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
733                         }
734
735                         ast_frfree(f);
736                         continue;
737                 } else if (ast_test_flag(flags, OPTION_WHISPER) && f->frametype == AST_FRAME_VOICE) {
738                         ast_audiohook_lock(&csth.whisper_audiohook);
739                         ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
740                         ast_audiohook_unlock(&csth.whisper_audiohook);
741                         ast_frfree(f);
742                         continue;
743                 }
744
745                 res = (f->frametype == AST_FRAME_DTMF) ? f->subclass.integer : 0;
746                 ast_frfree(f);
747                 if (!res)
748                         continue;
749
750                 if (x == sizeof(inp))
751                         x = 0;
752
753                 if (res < 0) {
754                         running = -1;
755                         break;
756                 }
757
758                 if (ast_test_flag(flags, OPTION_EXIT)) {
759                         char tmp[2];
760                         tmp[0] = res;
761                         tmp[1] = '\0';
762                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
763                                 ast_debug(1, "Got DTMF %c, goto context %s\n", tmp[0], exitcontext);
764                                 pbx_builtin_setvar_helper(chan, "SPY_CHANNEL", name);
765                                 running = -2;
766                                 break;
767                         } else {
768                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
769                         }
770                 } else if (res >= '0' && res <= '9') {
771                         if (ast_test_flag(flags, OPTION_DTMF_SWITCH_MODES)) {
772                                 change_spy_mode(res, flags);
773                         } else {
774                                 inp[x++] = res;
775                         }
776                 }
777
778                 if (res == user_options->cycle) {
779                         running = 0;
780                         break;
781                 } else if (res == user_options->exit) {
782                         running = -2;
783                         break;
784                 } else if (res == user_options->volume) {
785                         if (!ast_strlen_zero(inp)) {
786                                 running = atoi(inp);
787                                 break;
788                         }
789
790                         (*volfactor)++;
791                         if (*volfactor > 4)
792                                 *volfactor = -4;
793                         ast_verb(3, "Setting spy volume on %s to %d\n", ast_channel_name(chan), *volfactor);
794
795                         csth.volfactor = *volfactor;
796                         csth.spy_audiohook.options.read_volume = csth.volfactor;
797                         csth.spy_audiohook.options.write_volume = csth.volfactor;
798                 }
799         }
800
801         if (ast_test_flag(flags, OPTION_PRIVATE))
802                 ast_channel_stop_silence_generator(chan, silgen);
803         else
804                 ast_deactivate_generator(chan);
805
806         ast_channel_lock(chan);
807         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
808         ast_channel_unlock(chan);
809
810         if (ast_test_flag(flags, OPTION_WHISPER | OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
811                 ast_audiohook_lock(&csth.whisper_audiohook);
812                 ast_audiohook_detach(&csth.whisper_audiohook);
813                 ast_audiohook_unlock(&csth.whisper_audiohook);
814                 ast_audiohook_destroy(&csth.whisper_audiohook);
815         }
816
817         if (ast_test_flag(flags, OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
818                 ast_audiohook_lock(&csth.bridge_whisper_audiohook);
819                 ast_audiohook_detach(&csth.bridge_whisper_audiohook);
820                 ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
821                 ast_audiohook_destroy(&csth.bridge_whisper_audiohook);
822         }
823
824         ast_audiohook_lock(&csth.spy_audiohook);
825         ast_audiohook_detach(&csth.spy_audiohook);
826         ast_audiohook_unlock(&csth.spy_audiohook);
827         ast_audiohook_destroy(&csth.spy_audiohook);
828
829         if (spyee_bridge_autochan) {
830                 ast_autochan_destroy(spyee_bridge_autochan);
831         }
832
833         ast_verb(2, "Done Spying on channel %s\n", name);
834         publish_chanspy_message(chan, NULL, 0);
835
836         return running;
837 }
838
839 static struct ast_autochan *next_channel(struct ast_channel_iterator *iter,
840                 struct ast_autochan *autochan, struct ast_channel *chan)
841 {
842         struct ast_channel *next;
843         struct ast_autochan *autochan_store;
844         const size_t pseudo_len = strlen("DAHDI/pseudo");
845
846         if (!iter) {
847                 return NULL;
848         }
849
850         for (; (next = ast_channel_iterator_next(iter)); ast_channel_unref(next)) {
851                 if (!strncmp(ast_channel_name(next), "DAHDI/pseudo", pseudo_len)
852                         || next == chan) {
853                         continue;
854                 }
855
856                 autochan_store = ast_autochan_setup(next);
857                 ast_channel_unref(next);
858
859                 return autochan_store;
860         }
861         return NULL;
862 }
863
864 static int spy_sayname(struct ast_channel *chan, const char *mailbox, const char *context)
865 {
866         char *mailbox_id;
867
868         mailbox_id = ast_alloca(strlen(mailbox) + strlen(context) + 2);
869         sprintf(mailbox_id, "%s@%s", mailbox, context); /* Safe */
870         return ast_app_sayname(chan, mailbox_id);
871 }
872
873 static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
874         int volfactor, const int fd, struct spy_dtmf_options *user_options,
875         const char *mygroup, const char *myenforced, const char *spec, const char *exten,
876         const char *context, const char *mailbox, const char *name_context)
877 {
878         char nameprefix[AST_NAME_STRLEN];
879         char exitcontext[AST_MAX_CONTEXT] = "";
880         signed char zero_volume = 0;
881         int waitms;
882         int res;
883         int num_spyed_upon = 1;
884         struct ast_channel_iterator *iter = NULL;
885
886         if (ast_test_flag(flags, OPTION_EXIT)) {
887                 const char *c;
888                 ast_channel_lock(chan);
889                 if ((c = pbx_builtin_getvar_helper(chan, "SPY_EXIT_CONTEXT"))) {
890                         ast_copy_string(exitcontext, c, sizeof(exitcontext));
891                 } else if (!ast_strlen_zero(ast_channel_macrocontext(chan))) {
892                         ast_copy_string(exitcontext, ast_channel_macrocontext(chan), sizeof(exitcontext));
893                 } else {
894                         ast_copy_string(exitcontext, ast_channel_context(chan), sizeof(exitcontext));
895                 }
896                 ast_channel_unlock(chan);
897         }
898
899         if (ast_channel_state(chan) != AST_STATE_UP)
900                 ast_answer(chan);
901
902         ast_set_flag(ast_channel_flags(chan), AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
903
904         waitms = 100;
905
906         for (;;) {
907                 struct ast_autochan *autochan = NULL, *next_autochan = NULL;
908                 struct ast_channel *prev = NULL;
909
910                 if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) {
911                         res = ast_streamfile(chan, "beep", ast_channel_language(chan));
912                         if (!res)
913                                 res = ast_waitstream(chan, "");
914                         else if (res < 0) {
915                                 ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
916                                 break;
917                         }
918                         if (!ast_strlen_zero(exitcontext)) {
919                                 char tmp[2];
920                                 tmp[0] = res;
921                                 tmp[1] = '\0';
922                                 if (!ast_goto_if_exists(chan, exitcontext, tmp, 1))
923                                         goto exit;
924                                 else
925                                         ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
926                         }
927                 }
928
929                 /* Set up the iterator we'll be using during this call */
930                 if (!ast_strlen_zero(spec)) {
931                         if (ast_test_flag(flags, OPTION_UNIQUEID)) {
932                                 struct ast_channel *unique_chan;
933
934                                 unique_chan = ast_channel_get_by_name(spec);
935                                 if (!unique_chan) {
936                                         res = -1;
937                                         goto exit;
938                                 }
939                                 iter = ast_channel_iterator_by_name_new(ast_channel_name(unique_chan), 0);
940                                 ast_channel_unref(unique_chan);
941                         } else {
942                                 iter = ast_channel_iterator_by_name_new(spec, strlen(spec));
943                         }
944                 } else if (!ast_strlen_zero(exten)) {
945                         iter = ast_channel_iterator_by_exten_new(exten, context);
946                 } else {
947                         iter = ast_channel_iterator_all_new();
948                 }
949
950                 if (!iter) {
951                         res = -1;
952                         goto exit;
953                 }
954
955                 res = ast_waitfordigit(chan, waitms);
956                 if (res < 0) {
957                         iter = ast_channel_iterator_destroy(iter);
958                         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
959                         break;
960                 }
961                 if (!ast_strlen_zero(exitcontext)) {
962                         char tmp[2];
963                         tmp[0] = res;
964                         tmp[1] = '\0';
965                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
966                                 iter = ast_channel_iterator_destroy(iter);
967                                 goto exit;
968                         } else {
969                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
970                         }
971                 }
972
973                 /* reset for the next loop around, unless overridden later */
974                 waitms = 100;
975                 num_spyed_upon = 0;
976
977                 for (autochan = next_channel(iter, autochan, chan);
978                      autochan;
979                          prev = autochan->chan, ast_autochan_destroy(autochan),
980                      autochan = next_autochan ? next_autochan : 
981                                 next_channel(iter, autochan, chan), next_autochan = NULL) {
982                         int igrp = !mygroup;
983                         int ienf = !myenforced;
984
985                         if (autochan->chan == prev) {
986                                 ast_autochan_destroy(autochan);
987                                 break;
988                         }
989
990                         if (ast_check_hangup(chan)) {
991                                 ast_autochan_destroy(autochan);
992                                 break;
993                         }
994
995                         if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_channel_is_bridged(autochan->chan)) {
996                                 continue;
997                         }
998
999                         if (ast_check_hangup(autochan->chan) || ast_test_flag(ast_channel_flags(autochan->chan), AST_FLAG_SPYING)) {
1000                                 continue;
1001                         }
1002
1003                         if (mygroup) {
1004                                 int num_groups = 0;
1005                                 int num_mygroups = 0;
1006                                 char dup_group[512];
1007                                 char dup_mygroup[512];
1008                                 char *groups[NUM_SPYGROUPS];
1009                                 char *mygroups[NUM_SPYGROUPS];
1010                                 const char *group = NULL;
1011                                 int x;
1012                                 int y;
1013                                 ast_copy_string(dup_mygroup, mygroup, sizeof(dup_mygroup));
1014                                 num_mygroups = ast_app_separate_args(dup_mygroup, ':', mygroups,
1015                                         ARRAY_LEN(mygroups));
1016
1017                                 /* Before dahdi scan was part of chanspy, it would use the "GROUP" variable 
1018                                  * rather than "SPYGROUP", this check is done to preserve expected behavior */
1019                                 if (ast_test_flag(flags, OPTION_DAHDI_SCAN)) {
1020                                         group = pbx_builtin_getvar_helper(autochan->chan, "GROUP");
1021                                 } else {
1022                                         group = pbx_builtin_getvar_helper(autochan->chan, "SPYGROUP");
1023                                 }
1024
1025                                 if (!ast_strlen_zero(group)) {
1026                                         ast_copy_string(dup_group, group, sizeof(dup_group));
1027                                         num_groups = ast_app_separate_args(dup_group, ':', groups,
1028                                                 ARRAY_LEN(groups));
1029                                 }
1030
1031                                 for (y = 0; y < num_mygroups; y++) {
1032                                         for (x = 0; x < num_groups; x++) {
1033                                                 if (!strcmp(mygroups[y], groups[x])) {
1034                                                         igrp = 1;
1035                                                         break;
1036                                                 }
1037                                         }
1038                                 }
1039                         }
1040
1041                         if (!igrp) {
1042                                 continue;
1043                         }
1044                         if (myenforced) {
1045                                 char ext[AST_CHANNEL_NAME + 3];
1046                                 char buffer[512];
1047                                 char *end;
1048
1049                                 snprintf(buffer, sizeof(buffer) - 1, ":%s:", myenforced);
1050
1051                                 ast_copy_string(ext + 1, ast_channel_name(autochan->chan), sizeof(ext) - 1);
1052                                 if ((end = strchr(ext, '-'))) {
1053                                         *end++ = ':';
1054                                         *end = '\0';
1055                                 }
1056
1057                                 ext[0] = ':';
1058
1059                                 if (strcasestr(buffer, ext)) {
1060                                         ienf = 1;
1061                                 }
1062                         }
1063
1064                         if (!ienf) {
1065                                 continue;
1066                         }
1067
1068                         if (!ast_test_flag(flags, OPTION_QUIET)) {
1069                                 char peer_name[AST_NAME_STRLEN + 5];
1070                                 char *ptr, *s;
1071
1072                                 strcpy(peer_name, "spy-");
1073                                 strncat(peer_name, ast_channel_name(autochan->chan), AST_NAME_STRLEN - 4 - 1);
1074                                 if ((ptr = strchr(peer_name, '/'))) {
1075                                         *ptr++ = '\0';
1076                                         for (s = peer_name; s < ptr; s++) {
1077                                                 *s = tolower(*s);
1078                                         }
1079                                         if ((s = strchr(ptr, '-'))) {
1080                                                 *s = '\0';
1081                                         }
1082                                 }
1083
1084                                 if (ast_test_flag(flags, OPTION_NAME)) {
1085                                         const char *local_context = S_OR(name_context, "default");
1086                                         const char *local_mailbox = S_OR(mailbox, ptr);
1087
1088                                         if (local_mailbox) {
1089                                                 res = spy_sayname(chan, local_mailbox, local_context);
1090                                         } else {
1091                                                 res = -1;
1092                                         }
1093                                 }
1094                                 if (!ast_test_flag(flags, OPTION_NAME) || res < 0) {
1095                                         int num;
1096                                         if (!ast_test_flag(flags, OPTION_NOTECH)) {
1097                                                 if (ast_fileexists(peer_name, NULL, NULL) > 0) {
1098                                                         res = ast_streamfile(chan, peer_name, ast_channel_language(chan));
1099                                                         if (!res) {
1100                                                                 res = ast_waitstream(chan, "");
1101                                                         }
1102                                                         if (res) {
1103                                                                 ast_autochan_destroy(autochan);
1104                                                                 break;
1105                                                         }
1106                                                 } else {
1107                                                         res = ast_say_character_str(chan, peer_name, "", ast_channel_language(chan), AST_SAY_CASE_NONE);
1108                                                 }
1109                                         }
1110                                         if (ptr && (num = atoi(ptr))) {
1111                                                 ast_say_digits(chan, num, "", ast_channel_language(chan));
1112                                         }
1113                                 }
1114                         }
1115
1116                         res = channel_spy(chan, autochan, &volfactor, fd, user_options, flags, exitcontext);
1117                         num_spyed_upon++;
1118
1119                         if (res == -1) {
1120                                 ast_autochan_destroy(autochan);
1121                                 iter = ast_channel_iterator_destroy(iter);
1122                                 goto exit;
1123                         } else if (res == -2) {
1124                                 res = 0;
1125                                 ast_autochan_destroy(autochan);
1126                                 iter = ast_channel_iterator_destroy(iter);
1127                                 goto exit;
1128                         } else if (res > 1 && spec && !ast_test_flag(flags, OPTION_UNIQUEID)) {
1129                                 struct ast_channel *next;
1130
1131                                 snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);
1132
1133                                 if ((next = ast_channel_get_by_name_prefix(nameprefix, strlen(nameprefix)))) {
1134                                         next_autochan = ast_autochan_setup(next);
1135                                         next = ast_channel_unref(next);
1136                                 } else {
1137                                         /* stay on this channel, if it is still valid */
1138                                         if (!ast_check_hangup(autochan->chan)) {
1139                                                 next_autochan = ast_autochan_setup(autochan->chan);
1140                                         } else {
1141                                                 /* the channel is gone */
1142                                                 next_autochan = NULL;
1143                                         }
1144                                 }
1145                         } else if (res == 0 && ast_test_flag(flags, OPTION_EXITONHANGUP)) {
1146                                 ast_autochan_destroy(autochan);
1147                                 iter = ast_channel_iterator_destroy(iter);
1148                                 goto exit;
1149                         }
1150                 }
1151
1152                 iter = ast_channel_iterator_destroy(iter);
1153
1154                 if (res == -1 || ast_check_hangup(chan))
1155                         break;
1156                 if (ast_test_flag(flags, OPTION_STOP) && !next_autochan) {
1157                         break;
1158                 }
1159         }
1160 exit:
1161
1162         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
1163
1164         ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
1165
1166         return res;
1167 }
1168
1169 static int chanspy_exec(struct ast_channel *chan, const char *data)
1170 {
1171         char *myenforced = NULL;
1172         char *mygroup = NULL;
1173         char *recbase = NULL;
1174         int fd = 0;
1175         struct ast_flags flags;
1176         struct spy_dtmf_options user_options = {
1177                 .cycle = '*',
1178                 .volume = '#',
1179                 .exit = '\0',
1180         };
1181         RAII_VAR(struct ast_format *, oldwf, NULL, ao2_cleanup);
1182         int volfactor = 0;
1183         int res;
1184         char *mailbox = NULL;
1185         char *name_context = NULL;
1186         AST_DECLARE_APP_ARGS(args,
1187                 AST_APP_ARG(spec);
1188                 AST_APP_ARG(options);
1189         );
1190         char *opts[OPT_ARG_ARRAY_SIZE];
1191         char *parse = ast_strdupa(data);
1192
1193         AST_STANDARD_APP_ARGS(args, parse);
1194
1195         if (args.spec && !strcmp(args.spec, "all"))
1196                 args.spec = NULL;
1197
1198         if (args.options) {
1199                 char tmp;
1200                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
1201                 if (ast_test_flag(&flags, OPTION_GROUP))
1202                         mygroup = opts[OPT_ARG_GROUP];
1203
1204                 if (ast_test_flag(&flags, OPTION_RECORD) &&
1205                         !(recbase = opts[OPT_ARG_RECORD]))
1206                         recbase = "chanspy";
1207
1208                 if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
1209                         tmp = opts[OPT_ARG_EXIT][0];
1210                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1211                                 user_options.exit = tmp;
1212                         } else {
1213                                 ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.\n");
1214                         }
1215                 }
1216
1217                 if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
1218                         tmp = opts[OPT_ARG_CYCLE][0];
1219                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1220                                 user_options.cycle = tmp;
1221                         } else {
1222                                 ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.\n");
1223                         }
1224                 }
1225
1226                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
1227                         int vol;
1228
1229                         if ((sscanf(opts[OPT_ARG_VOLUME], "%30d", &vol) != 1) || (vol > 4) || (vol < -4))
1230                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
1231                         else
1232                                 volfactor = vol;
1233                 }
1234
1235                 if (ast_test_flag(&flags, OPTION_PRIVATE))
1236                         ast_set_flag(&flags, OPTION_WHISPER);
1237
1238                 if (ast_test_flag(&flags, OPTION_ENFORCED))
1239                         myenforced = opts[OPT_ARG_ENFORCED];
1240
1241                 if (ast_test_flag(&flags, OPTION_NAME)) {
1242                         if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
1243                                 char *delimiter;
1244                                 if ((delimiter = strchr(opts[OPT_ARG_NAME], '@'))) {
1245                                         mailbox = opts[OPT_ARG_NAME];
1246                                         *delimiter++ = '\0';
1247                                         name_context = delimiter;
1248                                 } else {
1249                                         mailbox = opts[OPT_ARG_NAME];
1250                                 }
1251                         }
1252                 }
1253         } else {
1254                 ast_clear_flag(&flags, AST_FLAGS_ALL);
1255         }
1256
1257         oldwf = ao2_bump(ast_channel_writeformat(chan));
1258         if (ast_set_write_format(chan, ast_format_slin) < 0) {
1259                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1260                 return -1;
1261         }
1262
1263         if (recbase) {
1264                 char filename[PATH_MAX];
1265
1266                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
1267                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
1268                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
1269                         fd = 0;
1270                 }
1271         }
1272
1273         res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, myenforced, args.spec, NULL, NULL, mailbox, name_context);
1274
1275         if (fd)
1276                 close(fd);
1277
1278         if (oldwf && ast_set_write_format(chan, oldwf) < 0)
1279                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1280
1281         if (ast_test_flag(&flags, OPTION_EXITONHANGUP)) {
1282                 ast_verb(3, "Stopped spying due to the spied-on channel hanging up.\n");
1283         }
1284
1285         return res;
1286 }
1287
1288 static int extenspy_exec(struct ast_channel *chan, const char *data)
1289 {
1290         char *ptr, *exten = NULL;
1291         char *mygroup = NULL;
1292         char *recbase = NULL;
1293         int fd = 0;
1294         struct ast_flags flags;
1295         struct spy_dtmf_options user_options = {
1296                 .cycle = '*',
1297                 .volume = '#',
1298                 .exit = '\0',
1299         };
1300         RAII_VAR(struct ast_format *, oldwf, NULL, ao2_cleanup);
1301         int volfactor = 0;
1302         int res;
1303         char *mailbox = NULL;
1304         char *name_context = NULL;
1305         AST_DECLARE_APP_ARGS(args,
1306                 AST_APP_ARG(context);
1307                 AST_APP_ARG(options);
1308         );
1309         char *parse = ast_strdupa(data);
1310
1311         AST_STANDARD_APP_ARGS(args, parse);
1312
1313         if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
1314                 exten = args.context;
1315                 *ptr++ = '\0';
1316                 args.context = ptr;
1317         }
1318         if (ast_strlen_zero(args.context))
1319                 args.context = ast_strdupa(ast_channel_context(chan));
1320
1321         if (args.options) {
1322                 char *opts[OPT_ARG_ARRAY_SIZE];
1323                 char tmp;
1324
1325                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
1326                 if (ast_test_flag(&flags, OPTION_GROUP))
1327                         mygroup = opts[OPT_ARG_GROUP];
1328
1329                 if (ast_test_flag(&flags, OPTION_RECORD) &&
1330                         !(recbase = opts[OPT_ARG_RECORD]))
1331                         recbase = "chanspy";
1332
1333                 if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
1334                         tmp = opts[OPT_ARG_EXIT][0];
1335                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1336                                 user_options.exit = tmp;
1337                         } else {
1338                                 ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.\n");
1339                         }
1340                 }
1341
1342                 if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
1343                         tmp = opts[OPT_ARG_CYCLE][0];
1344                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1345                                 user_options.cycle = tmp;
1346                         } else {
1347                                 ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.\n");
1348                         }
1349                 }
1350
1351                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
1352                         int vol;
1353
1354                         if ((sscanf(opts[OPT_ARG_VOLUME], "%30d", &vol) != 1) || (vol > 4) || (vol < -4))
1355                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
1356                         else
1357                                 volfactor = vol;
1358                 }
1359
1360                 if (ast_test_flag(&flags, OPTION_PRIVATE))
1361                         ast_set_flag(&flags, OPTION_WHISPER);
1362
1363                 if (ast_test_flag(&flags, OPTION_NAME)) {
1364                         if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
1365                                 char *delimiter;
1366                                 if ((delimiter = strchr(opts[OPT_ARG_NAME], '@'))) {
1367                                         mailbox = opts[OPT_ARG_NAME];
1368                                         *delimiter++ = '\0';
1369                                         name_context = delimiter;
1370                                 } else {
1371                                         mailbox = opts[OPT_ARG_NAME];
1372                                 }
1373                         }
1374                 }
1375
1376         } else {
1377                 /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
1378                 ast_clear_flag(&flags, AST_FLAGS_ALL);
1379         }
1380
1381         oldwf = ao2_bump(ast_channel_writeformat(chan));
1382         if (ast_set_write_format(chan, ast_format_slin) < 0) {
1383                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1384                 return -1;
1385         }
1386
1387         if (recbase) {
1388                 char filename[PATH_MAX];
1389
1390                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
1391                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
1392                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
1393                         fd = 0;
1394                 }
1395         }
1396
1397
1398         res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, NULL, NULL, exten, args.context, mailbox, name_context);
1399
1400         if (fd)
1401                 close(fd);
1402
1403         if (oldwf && ast_set_write_format(chan, oldwf) < 0)
1404                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1405
1406         return res;
1407 }
1408
1409 static int dahdiscan_exec(struct ast_channel *chan, const char *data)
1410 {
1411         const char *spec = "DAHDI";
1412         struct ast_flags flags;
1413         struct spy_dtmf_options user_options = {
1414                 .cycle = '#',
1415                 .volume = '\0',
1416                 .exit = '*',
1417         };
1418         struct ast_format *oldwf;
1419         int res;
1420         char *mygroup = NULL;
1421
1422         /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
1423         ast_clear_flag(&flags, AST_FLAGS_ALL);
1424
1425         if (!ast_strlen_zero(data)) {
1426                 mygroup = ast_strdupa(data);
1427         }
1428         ast_set_flag(&flags, OPTION_DTMF_EXIT);
1429         ast_set_flag(&flags, OPTION_DTMF_CYCLE);
1430         ast_set_flag(&flags, OPTION_DAHDI_SCAN);
1431
1432         oldwf = ao2_bump(ast_channel_writeformat(chan));
1433         if (ast_set_write_format(chan, ast_format_slin) < 0) {
1434                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1435                 ao2_cleanup(oldwf);
1436                 return -1;
1437         }
1438
1439         res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);
1440
1441         if (oldwf && ast_set_write_format(chan, oldwf) < 0)
1442                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1443         ao2_cleanup(oldwf);
1444
1445         return res;
1446 }
1447
1448 static int unload_module(void)
1449 {
1450         int res = 0;
1451
1452         res |= ast_unregister_application(app_chan);
1453         res |= ast_unregister_application(app_ext);
1454         res |= ast_unregister_application(app_dahdiscan);
1455
1456         return res;
1457 }
1458
1459 static int load_module(void)
1460 {
1461         int res = 0;
1462
1463         res |= ast_register_application_xml(app_chan, chanspy_exec);
1464         res |= ast_register_application_xml(app_ext, extenspy_exec);
1465         res |= ast_register_application_xml(app_dahdiscan, dahdiscan_exec);
1466
1467         return res;
1468 }
1469
1470 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Listen to the audio of an active channel");