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