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