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