Merge "AST-2018-005: Fix tdata leaks when calling pjsip_endpt_send_response(2)"
[asterisk/asterisk.git] / apps / app_mixmonitor.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2005, Anthony Minessale II
5  * Copyright (C) 2005 - 2006, Digium, Inc.
6  *
7  * Mark Spencer <markster@digium.com>
8  * Kevin P. Fleming <kpfleming@digium.com>
9  *
10  * Based on app_muxmon.c provided by
11  * Anthony Minessale II <anthmct@yahoo.com>
12  *
13  * See http://www.asterisk.org for more information about
14  * the Asterisk project. Please do not directly contact
15  * any of the maintainers of this project for assistance;
16  * the project provides a web site, mailing lists and IRC
17  * channels for your use.
18  *
19  * This program is free software, distributed under the terms of
20  * the GNU General Public License Version 2. See the LICENSE file
21  * at the top of the source tree.
22  */
23
24 /*! \file
25  *
26  * \brief MixMonitor() - Record a call and mix the audio during the recording
27  * \ingroup applications
28  *
29  * \author Mark Spencer <markster@digium.com>
30  * \author Kevin P. Fleming <kpfleming@digium.com>
31  *
32  * \note Based on app_muxmon.c provided by
33  * Anthony Minessale II <anthmct@yahoo.com>
34  */
35
36 /*** MODULEINFO
37         <use type="module">func_periodic_hook</use>
38         <support_level>core</support_level>
39  ***/
40
41 #include "asterisk.h"
42
43 #include "asterisk/paths.h"     /* use ast_config_AST_MONITOR_DIR */
44 #include "asterisk/stringfields.h"
45 #include "asterisk/file.h"
46 #include "asterisk/audiohook.h"
47 #include "asterisk/pbx.h"
48 #include "asterisk/module.h"
49 #include "asterisk/cli.h"
50 #include "asterisk/app.h"
51 #include "asterisk/channel.h"
52 #include "asterisk/autochan.h"
53 #include "asterisk/manager.h"
54 #include "asterisk/callerid.h"
55 #include "asterisk/mod_format.h"
56 #include "asterisk/linkedlists.h"
57 #include "asterisk/test.h"
58 #include "asterisk/mixmonitor.h"
59 #include "asterisk/format_cache.h"
60 #include "asterisk/beep.h"
61
62 /*** DOCUMENTATION
63         <application name="MixMonitor" language="en_US">
64                 <synopsis>
65                         Record a call and mix the audio during the recording.  Use of StopMixMonitor is required
66                         to guarantee the audio file is available for processing during dialplan execution.
67                 </synopsis>
68                 <syntax>
69                         <parameter name="file" required="true" argsep=".">
70                                 <argument name="filename" required="true">
71                                         <para>If <replaceable>filename</replaceable> is an absolute path, uses that path, otherwise
72                                         creates the file in the configured monitoring directory from <filename>asterisk.conf.</filename></para>
73                                 </argument>
74                                 <argument name="extension" required="true" />
75                         </parameter>
76                         <parameter name="options">
77                                 <optionlist>
78                                         <option name="a">
79                                                 <para>Append to the file instead of overwriting it.</para>
80                                         </option>
81                                         <option name="b">
82                                                 <para>Only save audio to the file while the channel is bridged.</para>
83                                                 <note><para>If you utilize this option inside a Local channel, you must make sure the Local
84                                                 channel is not optimized away. To do this, be sure to call your Local channel with the
85                                                 <literal>/n</literal> option. For example: Dial(Local/start@mycontext/n)</para></note>
86                                         </option>
87                                         <option name="B">
88                                                 <para>Play a periodic beep while this call is being recorded.</para>
89                                                 <argument name="interval"><para>Interval, in seconds. Default is 15.</para></argument>
90                                         </option>
91                                         <option name="v">
92                                                 <para>Adjust the <emphasis>heard</emphasis> volume by a factor of <replaceable>x</replaceable>
93                                                 (range <literal>-4</literal> to <literal>4</literal>)</para>
94                                                 <argument name="x" required="true" />
95                                         </option>
96                                         <option name="V">
97                                                 <para>Adjust the <emphasis>spoken</emphasis> volume by a factor
98                                                 of <replaceable>x</replaceable> (range <literal>-4</literal> to <literal>4</literal>)</para>
99                                                 <argument name="x" required="true" />
100                                         </option>
101                                         <option name="W">
102                                                 <para>Adjust both, <emphasis>heard and spoken</emphasis> volumes by a factor
103                                                 of <replaceable>x</replaceable> (range <literal>-4</literal> to <literal>4</literal>)</para>
104                                                 <argument name="x" required="true" />
105                                         </option>
106                                         <option name="r">
107                                                 <argument name="file" required="true" />
108                                                 <para>Use the specified file to record the <emphasis>receive</emphasis> audio feed.
109                                                 Like with the basic filename argument, if an absolute path isn't given, it will create
110                                                 the file in the configured monitoring directory.</para>
111                                         </option>
112                                         <option name="t">
113                                                 <argument name="file" required="true" />
114                                                 <para>Use the specified file to record the <emphasis>transmit</emphasis> audio feed.
115                                                 Like with the basic filename argument, if an absolute path isn't given, it will create
116                                                 the file in the configured monitoring directory.</para>
117                                         </option>
118                                         <option name="i">
119                                                 <argument name="chanvar" required="true" />
120                                                 <para>Stores the MixMonitor's ID on this channel variable.</para>
121                                         </option>
122                                         <option name="p">
123                                                 <para>Play a beep on the channel that starts the recording.</para>
124                                         </option>
125                                         <option name="P">
126                                                 <para>Play a beep on the channel that stops the recording.</para>
127                                         </option>
128                                         <option name="m">
129                                                 <argument name="mailbox" required="true" />
130                                                 <para>Create a copy of the recording as a voicemail in the indicated <emphasis>mailbox</emphasis>(es)
131                                                 separated by commas eg. m(1111@default,2222@default,...).  Folders can be optionally specified using
132                                                 the syntax: mailbox@context/folder</para>
133                                         </option>
134                                 </optionlist>
135                         </parameter>
136                         <parameter name="command">
137                                 <para>Will be executed when the recording is over.</para>
138                                 <para>Any strings matching <literal>^{X}</literal> will be unescaped to <variable>X</variable>.</para>
139                                 <para>All variables will be evaluated at the time MixMonitor is called.</para>
140                                 <warning><para>Do not use untrusted strings such as <variable>CALLERID(num)</variable>
141                                 or <variable>CALLERID(name)</variable> as part of the command parameters.  You
142                                 risk a command injection attack executing arbitrary commands if the untrusted
143                                 strings aren't filtered to remove dangerous characters.  See function
144                                 <variable>FILTER()</variable>.</para></warning>
145                         </parameter>
146                 </syntax>
147                 <description>
148                         <para>Records the audio on the current channel to the specified file.</para>
149                         <para>This application does not automatically answer and should be preceeded by
150                         an application such as Answer or Progress().</para>
151                         <note><para>MixMonitor runs as an audiohook.</para></note>
152                         <variablelist>
153                                 <variable name="MIXMONITOR_FILENAME">
154                                         <para>Will contain the filename used to record.</para>
155                                 </variable>
156                         </variablelist>
157                         <warning><para>Do not use untrusted strings such as <variable>CALLERID(num)</variable>
158                         or <variable>CALLERID(name)</variable> as part of ANY of the application's
159                         parameters.  You risk a command injection attack executing arbitrary commands
160                         if the untrusted strings aren't filtered to remove dangerous characters.  See
161                         function <variable>FILTER()</variable>.</para></warning>
162                 </description>
163                 <see-also>
164                         <ref type="application">Monitor</ref>
165                         <ref type="application">StopMixMonitor</ref>
166                         <ref type="application">PauseMonitor</ref>
167                         <ref type="application">UnpauseMonitor</ref>
168                         <ref type="function">AUDIOHOOK_INHERIT</ref>
169                 </see-also>
170         </application>
171         <application name="StopMixMonitor" language="en_US">
172                 <synopsis>
173                         Stop recording a call through MixMonitor, and free the recording's file handle.
174                 </synopsis>
175                 <syntax>
176                         <parameter name="MixMonitorID" required="false">
177                                 <para>If a valid ID is provided, then this command will stop only that specific
178                                 MixMonitor.</para>
179                         </parameter>
180                 </syntax>
181                 <description>
182                         <para>Stops the audio recording that was started with a call to <literal>MixMonitor()</literal>
183                         on the current channel.</para>
184                 </description>
185                 <see-also>
186                         <ref type="application">MixMonitor</ref>
187                 </see-also>
188         </application>
189         <manager name="MixMonitorMute" language="en_US">
190                 <synopsis>
191                         Mute / unMute a Mixmonitor recording.
192                 </synopsis>
193                 <syntax>
194                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
195                         <parameter name="Channel" required="true">
196                                 <para>Used to specify the channel to mute.</para>
197                         </parameter>
198                         <parameter name="Direction">
199                                 <para>Which part of the recording to mute:  read, write or both (from channel, to channel or both channels).</para>
200                         </parameter>
201                         <parameter name="State">
202                                 <para>Turn mute on or off : 1 to turn on, 0 to turn off.</para>
203                         </parameter>
204                 </syntax>
205                 <description>
206                         <para>This action may be used to mute a MixMonitor recording.</para>
207                 </description>
208         </manager>
209         <manager name="MixMonitor" language="en_US">
210                 <synopsis>
211                         Record a call and mix the audio during the recording.  Use of StopMixMonitor is required
212                         to guarantee the audio file is available for processing during dialplan execution.
213                 </synopsis>
214                 <syntax>
215                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
216                         <parameter name="Channel" required="true">
217                                 <para>Used to specify the channel to record.</para>
218                         </parameter>
219                         <parameter name="File">
220                                 <para>Is the name of the file created in the monitor spool directory.
221                                 Defaults to the same name as the channel (with slashes replaced with dashes).
222                                 This argument is optional if you specify to record unidirectional audio with
223                                 either the r(filename) or t(filename) options in the options field. If
224                                 neither MIXMONITOR_FILENAME or this parameter is set, the mixed stream won't
225                                 be recorded.</para>
226                         </parameter>
227                         <parameter name="options">
228                                 <para>Options that apply to the MixMonitor in the same way as they
229                                 would apply if invoked from the MixMonitor application. For a list of
230                                 available options, see the documentation for the mixmonitor application. </para>
231                         </parameter>
232                         <parameter name="Command">
233                                 <para>Will be executed when the recording is over.
234                                 Any strings matching <literal>^{X}</literal> will be unescaped to <variable>X</variable>.
235                                 All variables will be evaluated at the time MixMonitor is called.</para>
236                                 <warning><para>Do not use untrusted strings such as <variable>CALLERID(num)</variable>
237                                 or <variable>CALLERID(name)</variable> as part of the command parameters.  You
238                                 risk a command injection attack executing arbitrary commands if the untrusted
239                                 strings aren't filtered to remove dangerous characters.  See function
240                                 <variable>FILTER()</variable>.</para></warning>
241                         </parameter>
242                 </syntax>
243                 <description>
244                         <para>This action records the audio on the current channel to the specified file.</para>
245                         <variablelist>
246                                 <variable name="MIXMONITOR_FILENAME">
247                                         <para>Will contain the filename used to record the mixed stream.</para>
248                                 </variable>
249                         </variablelist>
250                 </description>
251         </manager>
252         <manager name="StopMixMonitor" language="en_US">
253                 <synopsis>
254                         Stop recording a call through MixMonitor, and free the recording's file handle.
255                 </synopsis>
256                 <syntax>
257                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
258                         <parameter name="Channel" required="true">
259                                 <para>The name of the channel monitored.</para>
260                         </parameter>
261                         <parameter name="MixMonitorID" required="false">
262                                 <para>If a valid ID is provided, then this command will stop only that specific
263                                 MixMonitor.</para>
264                         </parameter>
265                 </syntax>
266                 <description>
267                         <para>This action stops the audio recording that was started with the <literal>MixMonitor</literal>
268                         action on the current channel.</para>
269                 </description>
270         </manager>
271         <function name="MIXMONITOR" language="en_US">
272                 <synopsis>
273                         Retrieve data pertaining to specific instances of MixMonitor on a channel.
274                 </synopsis>
275                 <syntax>
276                         <parameter name="id" required="true">
277                                 <para>The unique ID of the MixMonitor instance. The unique ID can be retrieved through the channel
278                                 variable used as an argument to the <replaceable>i</replaceable> option to MixMonitor.</para>
279                         </parameter>
280                         <parameter name="key" required="true">
281                                 <para>The piece of data to retrieve from the MixMonitor.</para>
282                                 <enumlist>
283                                         <enum name="filename" />
284                                 </enumlist>
285                         </parameter>
286                 </syntax>
287         </function>
288
289  ***/
290
291 #define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
292
293 static const char * const app = "MixMonitor";
294
295 static const char * const stop_app = "StopMixMonitor";
296
297 static const char * const mixmonitor_spy_type = "MixMonitor";
298
299 /*!
300  * \internal
301  * \brief This struct is a list item holds data needed to find a vm_recipient within voicemail
302  */
303 struct vm_recipient {
304         char mailbox[AST_MAX_CONTEXT];
305         char context[AST_MAX_EXTENSION];
306         char folder[80];
307         AST_LIST_ENTRY(vm_recipient) list;
308 };
309
310 struct mixmonitor {
311         struct ast_audiohook audiohook;
312         char *filename;
313         char *filename_read;
314         char *filename_write;
315         char *post_process;
316         char *name;
317         ast_callid callid;
318         unsigned int flags;
319         struct ast_autochan *autochan;
320         struct mixmonitor_ds *mixmonitor_ds;
321
322         /* the below string fields describe data used for creating voicemails from the recording */
323         AST_DECLARE_STRING_FIELDS(
324                 AST_STRING_FIELD(call_context);
325                 AST_STRING_FIELD(call_macrocontext);
326                 AST_STRING_FIELD(call_extension);
327                 AST_STRING_FIELD(call_callerchan);
328                 AST_STRING_FIELD(call_callerid);
329         );
330         int call_priority;
331
332         /* FUTURE DEVELOPMENT NOTICE
333          * recipient_list will need locks if we make it editable after the monitor is started */
334         AST_LIST_HEAD_NOLOCK(, vm_recipient) recipient_list;
335 };
336
337 enum mixmonitor_flags {
338         MUXFLAG_APPEND = (1 << 1),
339         MUXFLAG_BRIDGED = (1 << 2),
340         MUXFLAG_VOLUME = (1 << 3),
341         MUXFLAG_READVOLUME = (1 << 4),
342         MUXFLAG_WRITEVOLUME = (1 << 5),
343         MUXFLAG_READ = (1 << 6),
344         MUXFLAG_WRITE = (1 << 7),
345         MUXFLAG_COMBINED = (1 << 8),
346         MUXFLAG_UID = (1 << 9),
347         MUXFLAG_VMRECIPIENTS = (1 << 10),
348         MUXFLAG_BEEP = (1 << 11),
349         MUXFLAG_BEEP_START = (1 << 12),
350         MUXFLAG_BEEP_STOP = (1 << 13)
351 };
352
353 enum mixmonitor_args {
354         OPT_ARG_READVOLUME = 0,
355         OPT_ARG_WRITEVOLUME,
356         OPT_ARG_VOLUME,
357         OPT_ARG_WRITENAME,
358         OPT_ARG_READNAME,
359         OPT_ARG_UID,
360         OPT_ARG_VMRECIPIENTS,
361         OPT_ARG_BEEP_INTERVAL,
362         OPT_ARG_ARRAY_SIZE,     /* Always last element of the enum */
363 };
364
365 AST_APP_OPTIONS(mixmonitor_opts, {
366         AST_APP_OPTION('a', MUXFLAG_APPEND),
367         AST_APP_OPTION('b', MUXFLAG_BRIDGED),
368         AST_APP_OPTION_ARG('B', MUXFLAG_BEEP, OPT_ARG_BEEP_INTERVAL),
369         AST_APP_OPTION('p', MUXFLAG_BEEP_START),
370         AST_APP_OPTION('P', MUXFLAG_BEEP_STOP),
371         AST_APP_OPTION_ARG('v', MUXFLAG_READVOLUME, OPT_ARG_READVOLUME),
372         AST_APP_OPTION_ARG('V', MUXFLAG_WRITEVOLUME, OPT_ARG_WRITEVOLUME),
373         AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
374         AST_APP_OPTION_ARG('r', MUXFLAG_READ, OPT_ARG_READNAME),
375         AST_APP_OPTION_ARG('t', MUXFLAG_WRITE, OPT_ARG_WRITENAME),
376         AST_APP_OPTION_ARG('i', MUXFLAG_UID, OPT_ARG_UID),
377         AST_APP_OPTION_ARG('m', MUXFLAG_VMRECIPIENTS, OPT_ARG_VMRECIPIENTS),
378 });
379
380 struct mixmonitor_ds {
381         unsigned int destruction_ok;
382         ast_cond_t destruction_condition;
383         ast_mutex_t lock;
384
385         /* The filestream is held in the datastore so it can be stopped
386          * immediately during stop_mixmonitor or channel destruction. */
387         int fs_quit;
388
389         struct ast_filestream *fs;
390         struct ast_filestream *fs_read;
391         struct ast_filestream *fs_write;
392
393         struct ast_audiohook *audiohook;
394
395         unsigned int samp_rate;
396         char *filename;
397         char *beep_id;
398 };
399
400 /*!
401  * \internal
402  * \pre mixmonitor_ds must be locked before calling this function
403  */
404 static void mixmonitor_ds_close_fs(struct mixmonitor_ds *mixmonitor_ds)
405 {
406         unsigned char quitting = 0;
407
408         if (mixmonitor_ds->fs) {
409                 quitting = 1;
410                 ast_closestream(mixmonitor_ds->fs);
411                 mixmonitor_ds->fs = NULL;
412                 ast_verb(2, "MixMonitor close filestream (mixed)\n");
413         }
414
415         if (mixmonitor_ds->fs_read) {
416                 quitting = 1;
417                 ast_closestream(mixmonitor_ds->fs_read);
418                 mixmonitor_ds->fs_read = NULL;
419                 ast_verb(2, "MixMonitor close filestream (read)\n");
420         }
421
422         if (mixmonitor_ds->fs_write) {
423                 quitting = 1;
424                 ast_closestream(mixmonitor_ds->fs_write);
425                 mixmonitor_ds->fs_write = NULL;
426                 ast_verb(2, "MixMonitor close filestream (write)\n");
427         }
428
429         if (quitting) {
430                 mixmonitor_ds->fs_quit = 1;
431         }
432 }
433
434 static void mixmonitor_ds_destroy(void *data)
435 {
436         struct mixmonitor_ds *mixmonitor_ds = data;
437
438         ast_mutex_lock(&mixmonitor_ds->lock);
439         mixmonitor_ds->audiohook = NULL;
440         mixmonitor_ds->destruction_ok = 1;
441         ast_free(mixmonitor_ds->filename);
442         ast_free(mixmonitor_ds->beep_id);
443         ast_cond_signal(&mixmonitor_ds->destruction_condition);
444         ast_mutex_unlock(&mixmonitor_ds->lock);
445 }
446
447 static const struct ast_datastore_info mixmonitor_ds_info = {
448         .type = "mixmonitor",
449         .destroy = mixmonitor_ds_destroy,
450 };
451
452 static void destroy_monitor_audiohook(struct mixmonitor *mixmonitor)
453 {
454         if (mixmonitor->mixmonitor_ds) {
455                 ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
456                 mixmonitor->mixmonitor_ds->audiohook = NULL;
457                 ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
458         }
459         /* kill the audiohook.*/
460         ast_audiohook_lock(&mixmonitor->audiohook);
461         ast_audiohook_detach(&mixmonitor->audiohook);
462         ast_audiohook_unlock(&mixmonitor->audiohook);
463         ast_audiohook_destroy(&mixmonitor->audiohook);
464 }
465
466 static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook)
467 {
468         if (!chan) {
469                 return -1;
470         }
471
472         return ast_audiohook_attach(chan, audiohook);
473 }
474
475 /*!
476  * \internal
477  * \brief adds recipients to a mixmonitor's recipient list
478  * \param mixmonitor mixmonitor being affected
479  * \param vm_recipients string containing the desired recipients to add
480  */
481 static void add_vm_recipients_from_string(struct mixmonitor *mixmonitor, const char *vm_recipients)
482 {
483         /* recipients are in a single string with a format format resembling "mailbox@context/INBOX,mailbox2@context2,mailbox3@context3/Work" */
484         char *cur_mailbox = ast_strdupa(vm_recipients);
485         char *cur_context;
486         char *cur_folder;
487         char *next;
488         int elements_processed = 0;
489
490         while (!ast_strlen_zero(cur_mailbox)) {
491                 ast_debug(3, "attempting to add next element %d from %s\n", elements_processed, cur_mailbox);
492                 if ((next = strchr(cur_mailbox, ',')) || (next = strchr(cur_mailbox, '&'))) {
493                         *(next++) = '\0';
494                 }
495
496                 if ((cur_folder = strchr(cur_mailbox, '/'))) {
497                         *(cur_folder++) = '\0';
498                 } else {
499                         cur_folder = "INBOX";
500                 }
501
502                 if ((cur_context = strchr(cur_mailbox, '@'))) {
503                         *(cur_context++) = '\0';
504                 } else {
505                         cur_context = "default";
506                 }
507
508                 if (!ast_strlen_zero(cur_mailbox) && !ast_strlen_zero(cur_context)) {
509                         struct vm_recipient *recipient;
510                         if (!(recipient = ast_malloc(sizeof(*recipient)))) {
511                                 ast_log(LOG_ERROR, "Failed to allocate recipient. Aborting function.\n");
512                                 return;
513                         }
514                         ast_copy_string(recipient->context, cur_context, sizeof(recipient->context));
515                         ast_copy_string(recipient->mailbox, cur_mailbox, sizeof(recipient->mailbox));
516                         ast_copy_string(recipient->folder, cur_folder, sizeof(recipient->folder));
517
518                         /* Add to list */
519                         ast_verb(4, "Adding %s@%s to recipient list\n", recipient->mailbox, recipient->context);
520                         AST_LIST_INSERT_HEAD(&mixmonitor->recipient_list, recipient, list);
521                 } else {
522                         ast_log(LOG_ERROR, "Failed to properly parse extension and/or context from element %d of recipient string: %s\n", elements_processed, vm_recipients);
523                 }
524
525                 cur_mailbox = next;
526                 elements_processed++;
527         }
528 }
529
530 static void clear_mixmonitor_recipient_list(struct mixmonitor *mixmonitor)
531 {
532         struct vm_recipient *current;
533         while ((current = AST_LIST_REMOVE_HEAD(&mixmonitor->recipient_list, list))) {
534                 /* Clear list element data */
535                 ast_free(current);
536         }
537 }
538
539 #define SAMPLES_PER_FRAME 160
540
541 static void mixmonitor_free(struct mixmonitor *mixmonitor)
542 {
543         if (mixmonitor) {
544                 if (mixmonitor->mixmonitor_ds) {
545                         ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock);
546                         ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition);
547                         ast_free(mixmonitor->mixmonitor_ds);
548                 }
549
550                 ast_free(mixmonitor->name);
551                 ast_free(mixmonitor->post_process);
552                 ast_free(mixmonitor->filename);
553                 ast_free(mixmonitor->filename_write);
554                 ast_free(mixmonitor->filename_read);
555
556                 /* Free everything in the recipient list */
557                 clear_mixmonitor_recipient_list(mixmonitor);
558
559                 /* clean stringfields */
560                 ast_string_field_free_memory(mixmonitor);
561
562                 ast_free(mixmonitor);
563         }
564 }
565
566 /*!
567  * \internal
568  * \brief Copies the mixmonitor to all voicemail recipients
569  * \param mixmonitor The mixmonitor that needs to forward its file to recipients
570  * \param ext Format of the file that was saved
571  */
572 static void copy_to_voicemail(struct mixmonitor *mixmonitor, const char *ext, const char *filename)
573 {
574         struct vm_recipient *recipient = NULL;
575         struct ast_vm_recording_data recording_data;
576         if (ast_string_field_init(&recording_data, 512)) {
577                 ast_log(LOG_ERROR, "Failed to string_field_init, skipping copy_to_voicemail\n");
578                 return;
579         }
580
581         /* Copy strings to stringfields that will be used for all recipients */
582         ast_string_field_set(&recording_data, recording_file, filename);
583         ast_string_field_set(&recording_data, recording_ext, ext);
584         ast_string_field_set(&recording_data, call_context, mixmonitor->call_context);
585         ast_string_field_set(&recording_data, call_macrocontext, mixmonitor->call_macrocontext);
586         ast_string_field_set(&recording_data, call_extension, mixmonitor->call_extension);
587         ast_string_field_set(&recording_data, call_callerchan, mixmonitor->call_callerchan);
588         ast_string_field_set(&recording_data, call_callerid, mixmonitor->call_callerid);
589         /* and call_priority gets copied too */
590         recording_data.call_priority = mixmonitor->call_priority;
591
592         AST_LIST_TRAVERSE(&mixmonitor->recipient_list, recipient, list) {
593                 /* context, mailbox, and folder need to be set per recipient */
594                 ast_string_field_set(&recording_data, context, recipient->context);
595                 ast_string_field_set(&recording_data, mailbox, recipient->mailbox);
596                 ast_string_field_set(&recording_data, folder, recipient->folder);
597
598                 ast_verb(4, "MixMonitor attempting to send voicemail copy to %s@%s\n", recording_data.mailbox,
599                         recording_data.context);
600                 ast_app_copy_recording_to_vm(&recording_data);
601         }
602
603         /* Free the string fields for recording_data before exiting the function. */
604         ast_string_field_free_memory(&recording_data);
605 }
606
607 static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename, struct ast_filestream **fs, unsigned int *oflags, int *errflag, char **ext)
608 {
609         /* Initialize the file if not already done so */
610         char *last_slash = NULL;
611         if (!ast_strlen_zero(filename)) {
612                 if (!*fs && !*errflag && !mixmonitor->mixmonitor_ds->fs_quit) {
613                         *oflags = O_CREAT | O_WRONLY;
614                         *oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
615
616                         last_slash = strrchr(filename, '/');
617
618                         if ((*ext = strrchr(filename, '.')) && (*ext > last_slash)) {
619                                 **ext = '\0';
620                                 *ext = *ext + 1;
621                         } else {
622                                 *ext = "raw";
623                         }
624
625                         if (!(*fs = ast_writefile(filename, *ext, NULL, *oflags, 0, 0666))) {
626                                 ast_log(LOG_ERROR, "Cannot open %s.%s\n", filename, *ext);
627                                 *errflag = 1;
628                         } else {
629                                 struct ast_filestream *tmp = *fs;
630                                 mixmonitor->mixmonitor_ds->samp_rate = MAX(mixmonitor->mixmonitor_ds->samp_rate, ast_format_get_sample_rate(tmp->fmt->format));
631                         }
632                 }
633         }
634 }
635
636 static int mixmonitor_autochan_is_bridged(struct ast_autochan *autochan)
637 {
638         int is_bridged;
639
640         ast_autochan_channel_lock(autochan);
641         is_bridged = ast_channel_is_bridged(autochan->chan);
642         ast_autochan_channel_unlock(autochan);
643         return is_bridged;
644 }
645
646 static void *mixmonitor_thread(void *obj)
647 {
648         struct mixmonitor *mixmonitor = obj;
649         char *fs_ext = "";
650         char *fs_read_ext = "";
651         char *fs_write_ext = "";
652
653         struct ast_filestream **fs = NULL;
654         struct ast_filestream **fs_read = NULL;
655         struct ast_filestream **fs_write = NULL;
656
657         unsigned int oflags;
658         int errflag = 0;
659         struct ast_format *format_slin;
660
661         /* Keep callid association before any log messages */
662         if (mixmonitor->callid) {
663                 ast_callid_threadassoc_add(mixmonitor->callid);
664         }
665
666         ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name);
667
668         fs = &mixmonitor->mixmonitor_ds->fs;
669         fs_read = &mixmonitor->mixmonitor_ds->fs_read;
670         fs_write = &mixmonitor->mixmonitor_ds->fs_write;
671
672         ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
673         mixmonitor_save_prep(mixmonitor, mixmonitor->filename, fs, &oflags, &errflag, &fs_ext);
674         mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag, &fs_read_ext);
675         mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag, &fs_write_ext);
676
677         format_slin = ast_format_cache_get_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate);
678
679         ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
680
681         /* The audiohook must enter and exit the loop locked */
682         ast_audiohook_lock(&mixmonitor->audiohook);
683         while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) {
684                 struct ast_frame *fr = NULL;
685                 struct ast_frame *fr_read = NULL;
686                 struct ast_frame *fr_write = NULL;
687
688                 if (!(fr = ast_audiohook_read_frame_all(&mixmonitor->audiohook, SAMPLES_PER_FRAME, format_slin,
689                                                 &fr_read, &fr_write))) {
690                         ast_audiohook_trigger_wait(&mixmonitor->audiohook);
691
692                         if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
693                                 break;
694                         }
695                         continue;
696                 }
697
698                 /* audiohook lock is not required for the next block.
699                  * Unlock it, but remember to lock it before looping or exiting */
700                 ast_audiohook_unlock(&mixmonitor->audiohook);
701
702                 if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED)
703                         || mixmonitor_autochan_is_bridged(mixmonitor->autochan)) {
704                         ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
705
706                         /* Write out the frame(s) */
707                         if ((*fs_read) && (fr_read)) {
708                                 struct ast_frame *cur;
709
710                                 for (cur = fr_read; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
711                                         ast_writestream(*fs_read, cur);
712                                 }
713                         }
714
715                         if ((*fs_write) && (fr_write)) {
716                                 struct ast_frame *cur;
717
718                                 for (cur = fr_write; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
719                                         ast_writestream(*fs_write, cur);
720                                 }
721                         }
722
723                         if ((*fs) && (fr)) {
724                                 struct ast_frame *cur;
725
726                                 for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
727                                         ast_writestream(*fs, cur);
728                                 }
729                         }
730                         ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
731                 }
732                 /* All done! free it. */
733                 if (fr) {
734                         ast_frame_free(fr, 0);
735                 }
736                 if (fr_read) {
737                         ast_frame_free(fr_read, 0);
738                 }
739                 if (fr_write) {
740                         ast_frame_free(fr_write, 0);
741                 }
742
743                 fr = NULL;
744                 fr_write = NULL;
745                 fr_read = NULL;
746
747                 ast_audiohook_lock(&mixmonitor->audiohook);
748         }
749
750         ast_audiohook_unlock(&mixmonitor->audiohook);
751
752         if (ast_test_flag(mixmonitor, MUXFLAG_BEEP_STOP)) {
753                 ast_autochan_channel_lock(mixmonitor->autochan);
754                 ast_stream_and_wait(mixmonitor->autochan->chan, "beep", "");
755                 ast_autochan_channel_unlock(mixmonitor->autochan);
756         }
757
758         ast_autochan_destroy(mixmonitor->autochan);
759
760         /* Datastore cleanup.  close the filestream and wait for ds destruction */
761         ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
762         mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds);
763         if (!mixmonitor->mixmonitor_ds->destruction_ok) {
764                 ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock);
765         }
766         ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
767
768         /* kill the audiohook */
769         destroy_monitor_audiohook(mixmonitor);
770
771         if (mixmonitor->post_process) {
772                 ast_verb(2, "Executing [%s]\n", mixmonitor->post_process);
773                 ast_safe_system(mixmonitor->post_process);
774         }
775
776         ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name);
777         ast_test_suite_event_notify("MIXMONITOR_END", "File: %s\r\n", mixmonitor->filename);
778
779         if (!AST_LIST_EMPTY(&mixmonitor->recipient_list)) {
780                 if (ast_strlen_zero(fs_ext)) {
781                         ast_log(LOG_ERROR, "No file extension set for Mixmonitor %s. Skipping copy to voicemail.\n",
782                                 mixmonitor -> name);
783                 } else {
784                         ast_verb(3, "Copying recordings for Mixmonitor %s to voicemail recipients\n", mixmonitor->name);
785                         copy_to_voicemail(mixmonitor, fs_ext, mixmonitor->filename);
786                 }
787                 if (!ast_strlen_zero(fs_read_ext)) {
788                         ast_verb(3, "Copying read recording for Mixmonitor %s to voicemail recipients\n", mixmonitor->name);
789                         copy_to_voicemail(mixmonitor, fs_read_ext, mixmonitor->filename_read);
790                 }
791                 if (!ast_strlen_zero(fs_write_ext)) {
792                         ast_verb(3, "Copying write recording for Mixmonitor %s to voicemail recipients\n", mixmonitor->name);
793                         copy_to_voicemail(mixmonitor, fs_write_ext, mixmonitor->filename_write);
794                 }
795         } else {
796                 ast_debug(3, "No recipients to forward monitor to, moving on.\n");
797         }
798
799         mixmonitor_free(mixmonitor);
800
801         ast_module_unref(ast_module_info->self);
802         return NULL;
803 }
804
805 static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan, char **datastore_id, const char *beep_id)
806 {
807         struct ast_datastore *datastore = NULL;
808         struct mixmonitor_ds *mixmonitor_ds;
809
810         if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
811                 return -1;
812         }
813
814         if (ast_asprintf(datastore_id, "%p", mixmonitor_ds) == -1) {
815                 ast_log(LOG_ERROR, "Failed to allocate memory for MixMonitor ID.\n");
816                 ast_free(mixmonitor_ds);
817                 return -1;
818         }
819
820         ast_mutex_init(&mixmonitor_ds->lock);
821         ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);
822
823         if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, *datastore_id))) {
824                 ast_mutex_destroy(&mixmonitor_ds->lock);
825                 ast_cond_destroy(&mixmonitor_ds->destruction_condition);
826                 ast_free(mixmonitor_ds);
827                 return -1;
828         }
829
830         if (ast_test_flag(mixmonitor, MUXFLAG_BEEP_START)) {
831                 ast_autochan_channel_lock(mixmonitor->autochan);
832                 ast_stream_and_wait(mixmonitor->autochan->chan, "beep", "");
833                 ast_autochan_channel_unlock(mixmonitor->autochan);
834         }
835
836         mixmonitor_ds->samp_rate = 8000;
837         mixmonitor_ds->audiohook = &mixmonitor->audiohook;
838         mixmonitor_ds->filename = ast_strdup(mixmonitor->filename);
839         if (!ast_strlen_zero(beep_id)) {
840                 mixmonitor_ds->beep_id = ast_strdup(beep_id);
841         }
842         datastore->data = mixmonitor_ds;
843
844         ast_channel_lock(chan);
845         ast_channel_datastore_add(chan, datastore);
846         ast_channel_unlock(chan);
847
848         mixmonitor->mixmonitor_ds = mixmonitor_ds;
849         return 0;
850 }
851
852 static int launch_monitor_thread(struct ast_channel *chan, const char *filename,
853                                   unsigned int flags, int readvol, int writevol,
854                                   const char *post_process, const char *filename_write,
855                                   char *filename_read, const char *uid_channel_var,
856                                   const char *recipients, const char *beep_id)
857 {
858         pthread_t thread;
859         struct mixmonitor *mixmonitor;
860         char postprocess2[1024] = "";
861         char *datastore_id = NULL;
862
863         postprocess2[0] = 0;
864         /* If a post process system command is given attach it to the structure */
865         if (!ast_strlen_zero(post_process)) {
866                 char *p1, *p2;
867
868                 p1 = ast_strdupa(post_process);
869                 for (p2 = p1; *p2; p2++) {
870                         if (*p2 == '^' && *(p2+1) == '{') {
871                                 *p2 = '$';
872                         }
873                 }
874                 ast_channel_lock(chan);
875                 pbx_substitute_variables_helper(chan, p1, postprocess2, sizeof(postprocess2) - 1);
876                 ast_channel_unlock(chan);
877         }
878
879         /* Pre-allocate mixmonitor structure and spy */
880         if (!(mixmonitor = ast_calloc(1, sizeof(*mixmonitor)))) {
881                 return -1;
882         }
883
884         /* Now that the struct has been calloced, go ahead and initialize the string fields. */
885         if (ast_string_field_init(mixmonitor, 512)) {
886                 mixmonitor_free(mixmonitor);
887                 return -1;
888         }
889
890         /* Setup the actual spy before creating our thread */
891         if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type, 0)) {
892                 mixmonitor_free(mixmonitor);
893                 return -1;
894         }
895
896         /* Copy over flags and channel name */
897         mixmonitor->flags = flags;
898         if (!(mixmonitor->autochan = ast_autochan_setup(chan))) {
899                 mixmonitor_free(mixmonitor);
900                 return -1;
901         }
902
903         if (!ast_strlen_zero(filename)) {
904                 mixmonitor->filename = ast_strdup(filename);
905         }
906
907         if (!ast_strlen_zero(filename_write)) {
908                 mixmonitor->filename_write = ast_strdup(filename_write);
909         }
910
911         if (!ast_strlen_zero(filename_read)) {
912                 mixmonitor->filename_read = ast_strdup(filename_read);
913         }
914
915         if (setup_mixmonitor_ds(mixmonitor, chan, &datastore_id, beep_id)) {
916                 ast_autochan_destroy(mixmonitor->autochan);
917                 mixmonitor_free(mixmonitor);
918                 ast_free(datastore_id);
919                 return -1;
920         }
921
922         if (!ast_strlen_zero(uid_channel_var)) {
923                 if (datastore_id) {
924                         pbx_builtin_setvar_helper(chan, uid_channel_var, datastore_id);
925                 }
926         }
927         ast_free(datastore_id);
928
929         mixmonitor->name = ast_strdup(ast_channel_name(chan));
930
931         if (!ast_strlen_zero(postprocess2)) {
932                 mixmonitor->post_process = ast_strdup(postprocess2);
933         }
934
935         if (!ast_strlen_zero(recipients)) {
936                 char callerid[256];
937                 struct ast_party_connected_line *connected;
938
939                 ast_channel_lock(chan);
940
941                 /* We use the connected line of the invoking channel for caller ID. */
942
943                 connected = ast_channel_connected(chan);
944                 ast_debug(3, "Connected Line CID = %d - %s : %d - %s\n", connected->id.name.valid,
945                         connected->id.name.str, connected->id.number.valid,
946                         connected->id.number.str);
947                 ast_callerid_merge(callerid, sizeof(callerid),
948                         S_COR(connected->id.name.valid, connected->id.name.str, NULL),
949                         S_COR(connected->id.number.valid, connected->id.number.str, NULL),
950                         "Unknown");
951
952                 ast_string_field_set(mixmonitor, call_context, ast_channel_context(chan));
953                 ast_string_field_set(mixmonitor, call_macrocontext, ast_channel_macrocontext(chan));
954                 ast_string_field_set(mixmonitor, call_extension, ast_channel_exten(chan));
955                 ast_string_field_set(mixmonitor, call_callerchan, ast_channel_name(chan));
956                 ast_string_field_set(mixmonitor, call_callerid, callerid);
957                 mixmonitor->call_priority = ast_channel_priority(chan);
958
959                 ast_channel_unlock(chan);
960
961                 add_vm_recipients_from_string(mixmonitor, recipients);
962         }
963
964         ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
965
966         if (readvol)
967                 mixmonitor->audiohook.options.read_volume = readvol;
968         if (writevol)
969                 mixmonitor->audiohook.options.write_volume = writevol;
970
971         if (startmon(chan, &mixmonitor->audiohook)) {
972                 ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
973                         mixmonitor_spy_type, ast_channel_name(chan));
974                 ast_audiohook_destroy(&mixmonitor->audiohook);
975                 mixmonitor_free(mixmonitor);
976                 return -1;
977         }
978
979         /* reference be released at mixmonitor destruction */
980         mixmonitor->callid = ast_read_threadstorage_callid();
981
982         return ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
983 }
984
985 /* a note on filename_parse: creates directory structure and assigns absolute path from relative paths for filenames */
986 /* requires immediate copying of string from return to retain data since otherwise it will immediately lose scope */
987 static char *filename_parse(char *filename, char *buffer, size_t len)
988 {
989         char *slash;
990         if (ast_strlen_zero(filename)) {
991                 ast_log(LOG_WARNING, "No file name was provided for a file save option.\n");
992         } else if (filename[0] != '/') {
993                 char *build;
994                 build = ast_alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(filename) + 3);
995                 sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, filename);
996                 filename = build;
997         }
998
999         ast_copy_string(buffer, filename, len);
1000
1001         if ((slash = strrchr(filename, '/'))) {
1002                 *slash = '\0';
1003         }
1004         ast_mkdir(filename, 0777);
1005
1006         return buffer;
1007 }
1008
1009 static int mixmonitor_exec(struct ast_channel *chan, const char *data)
1010 {
1011         int x, readvol = 0, writevol = 0;
1012         char *filename_read = NULL;
1013         char *filename_write = NULL;
1014         char filename_buffer[1024] = "";
1015         char *uid_channel_var = NULL;
1016         char beep_id[64] = "";
1017
1018         struct ast_flags flags = { 0 };
1019         char *recipients = NULL;
1020         char *parse;
1021         AST_DECLARE_APP_ARGS(args,
1022                 AST_APP_ARG(filename);
1023                 AST_APP_ARG(options);
1024                 AST_APP_ARG(post_process);
1025         );
1026
1027         if (ast_strlen_zero(data)) {
1028                 ast_log(LOG_WARNING, "MixMonitor requires an argument (filename or ,t(filename) and/or r(filename)\n");
1029                 return -1;
1030         }
1031
1032         parse = ast_strdupa(data);
1033
1034         AST_STANDARD_APP_ARGS(args, parse);
1035
1036         if (args.options) {
1037                 char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
1038
1039                 ast_app_parse_options(mixmonitor_opts, &flags, opts, args.options);
1040
1041                 if (ast_test_flag(&flags, MUXFLAG_READVOLUME)) {
1042                         if (ast_strlen_zero(opts[OPT_ARG_READVOLUME])) {
1043                                 ast_log(LOG_WARNING, "No volume level was provided for the heard volume ('v') option.\n");
1044                         } else if ((sscanf(opts[OPT_ARG_READVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
1045                                 ast_log(LOG_NOTICE, "Heard volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_READVOLUME]);
1046                         } else {
1047                                 readvol = get_volfactor(x);
1048                         }
1049                 }
1050
1051                 if (ast_test_flag(&flags, MUXFLAG_WRITEVOLUME)) {
1052                         if (ast_strlen_zero(opts[OPT_ARG_WRITEVOLUME])) {
1053                                 ast_log(LOG_WARNING, "No volume level was provided for the spoken volume ('V') option.\n");
1054                         } else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
1055                                 ast_log(LOG_NOTICE, "Spoken volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_WRITEVOLUME]);
1056                         } else {
1057                                 writevol = get_volfactor(x);
1058                         }
1059                 }
1060
1061                 if (ast_test_flag(&flags, MUXFLAG_VOLUME)) {
1062                         if (ast_strlen_zero(opts[OPT_ARG_VOLUME])) {
1063                                 ast_log(LOG_WARNING, "No volume level was provided for the combined volume ('W') option.\n");
1064                         } else if ((sscanf(opts[OPT_ARG_VOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
1065                                 ast_log(LOG_NOTICE, "Combined volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_VOLUME]);
1066                         } else {
1067                                 readvol = writevol = get_volfactor(x);
1068                         }
1069                 }
1070
1071                 if (ast_test_flag(&flags, MUXFLAG_VMRECIPIENTS)) {
1072                         if (ast_strlen_zero(opts[OPT_ARG_VMRECIPIENTS])) {
1073                                 ast_log(LOG_WARNING, "No voicemail recipients were specified for the vm copy ('m') option.\n");
1074                         } else {
1075                                 recipients = ast_strdupa(opts[OPT_ARG_VMRECIPIENTS]);
1076                         }
1077                 }
1078
1079                 if (ast_test_flag(&flags, MUXFLAG_WRITE)) {
1080                         filename_write = ast_strdupa(filename_parse(opts[OPT_ARG_WRITENAME], filename_buffer, sizeof(filename_buffer)));
1081                 }
1082
1083                 if (ast_test_flag(&flags, MUXFLAG_READ)) {
1084                         filename_read = ast_strdupa(filename_parse(opts[OPT_ARG_READNAME], filename_buffer, sizeof(filename_buffer)));
1085                 }
1086
1087                 if (ast_test_flag(&flags, MUXFLAG_UID)) {
1088                         uid_channel_var = opts[OPT_ARG_UID];
1089                 }
1090
1091                 if (ast_test_flag(&flags, MUXFLAG_BEEP)) {
1092                         const char *interval_str = S_OR(opts[OPT_ARG_BEEP_INTERVAL], "15");
1093                         unsigned int interval = 15;
1094
1095                         if (sscanf(interval_str, "%30u", &interval) != 1) {
1096                                 ast_log(LOG_WARNING, "Invalid interval '%s' for periodic beep. Using default of %u\n",
1097                                                 interval_str, interval);
1098                         }
1099
1100                         if (ast_beep_start(chan, interval, beep_id, sizeof(beep_id))) {
1101                                 ast_log(LOG_WARNING, "Unable to enable periodic beep, please ensure func_periodic_hook is loaded.\n");
1102                                 return -1;
1103                         }
1104                 }
1105         }
1106         /* If there are no file writing arguments/options for the mix monitor, send a warning message and return -1 */
1107
1108         if (!ast_test_flag(&flags, MUXFLAG_WRITE) && !ast_test_flag(&flags, MUXFLAG_READ) && ast_strlen_zero(args.filename)) {
1109                 ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
1110                 return -1;
1111         }
1112
1113         /* If filename exists, try to create directories for it */
1114         if (!(ast_strlen_zero(args.filename))) {
1115                 args.filename = ast_strdupa(filename_parse(args.filename, filename_buffer, sizeof(filename_buffer)));
1116         }
1117
1118         pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
1119
1120         /* If launch_monitor_thread works, the module reference must not be released until it is finished. */
1121         ast_module_ref(ast_module_info->self);
1122         if (launch_monitor_thread(chan,
1123                         args.filename,
1124                         flags.flags,
1125                         readvol,
1126                         writevol,
1127                         args.post_process,
1128                         filename_write,
1129                         filename_read,
1130                         uid_channel_var,
1131                         recipients,
1132                         beep_id)) {
1133                 ast_module_unref(ast_module_info->self);
1134         }
1135
1136         return 0;
1137 }
1138
1139 static int stop_mixmonitor_full(struct ast_channel *chan, const char *data)
1140 {
1141         struct ast_datastore *datastore = NULL;
1142         char *parse = "";
1143         struct mixmonitor_ds *mixmonitor_ds;
1144         const char *beep_id = NULL;
1145
1146         AST_DECLARE_APP_ARGS(args,
1147                 AST_APP_ARG(mixmonid);
1148         );
1149
1150         if (!ast_strlen_zero(data)) {
1151                 parse = ast_strdupa(data);
1152         }
1153
1154         AST_STANDARD_APP_ARGS(args, parse);
1155
1156         ast_channel_lock(chan);
1157
1158         datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info,
1159                 S_OR(args.mixmonid, NULL));
1160         if (!datastore) {
1161                 ast_channel_unlock(chan);
1162                 return -1;
1163         }
1164         mixmonitor_ds = datastore->data;
1165
1166         ast_mutex_lock(&mixmonitor_ds->lock);
1167
1168         /* closing the filestream here guarantees the file is available to the dialplan
1169          * after calling StopMixMonitor */
1170         mixmonitor_ds_close_fs(mixmonitor_ds);
1171
1172         /* The mixmonitor thread may be waiting on the audiohook trigger.
1173          * In order to exit from the mixmonitor loop before waiting on channel
1174          * destruction, poke the audiohook trigger. */
1175         if (mixmonitor_ds->audiohook) {
1176                 if (mixmonitor_ds->audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
1177                         ast_audiohook_update_status(mixmonitor_ds->audiohook, AST_AUDIOHOOK_STATUS_SHUTDOWN);
1178                 }
1179                 ast_audiohook_lock(mixmonitor_ds->audiohook);
1180                 ast_cond_signal(&mixmonitor_ds->audiohook->trigger);
1181                 ast_audiohook_unlock(mixmonitor_ds->audiohook);
1182                 mixmonitor_ds->audiohook = NULL;
1183         }
1184
1185         if (!ast_strlen_zero(mixmonitor_ds->beep_id)) {
1186                 beep_id = ast_strdupa(mixmonitor_ds->beep_id);
1187         }
1188
1189         ast_mutex_unlock(&mixmonitor_ds->lock);
1190
1191         /* Remove the datastore so the monitor thread can exit */
1192         if (!ast_channel_datastore_remove(chan, datastore)) {
1193                 ast_datastore_free(datastore);
1194         }
1195
1196         ast_channel_unlock(chan);
1197
1198         if (!ast_strlen_zero(beep_id)) {
1199                 ast_beep_stop(chan, beep_id);
1200         }
1201
1202         return 0;
1203 }
1204
1205 static int stop_mixmonitor_exec(struct ast_channel *chan, const char *data)
1206 {
1207         stop_mixmonitor_full(chan, data);
1208         return 0;
1209 }
1210
1211 static char *handle_cli_mixmonitor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1212 {
1213         struct ast_channel *chan;
1214         struct ast_datastore *datastore = NULL;
1215         struct mixmonitor_ds *mixmonitor_ds = NULL;
1216
1217         switch (cmd) {
1218         case CLI_INIT:
1219                 e->command = "mixmonitor {start|stop|list}";
1220                 e->usage =
1221                         "Usage: mixmonitor start <chan_name> [args]\n"
1222                         "         The optional arguments are passed to the MixMonitor application.\n"
1223                         "       mixmonitor stop <chan_name> [args]\n"
1224                         "         The optional arguments are passed to the StopMixMonitor application.\n"
1225                         "       mixmonitor list <chan_name>\n";
1226                 return NULL;
1227         case CLI_GENERATE:
1228                 return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
1229         }
1230
1231         if (a->argc < 3) {
1232                 return CLI_SHOWUSAGE;
1233         }
1234
1235         if (!(chan = ast_channel_get_by_name_prefix(a->argv[2], strlen(a->argv[2])))) {
1236                 ast_cli(a->fd, "No channel matching '%s' found.\n", a->argv[2]);
1237                 /* Technically this is a failure, but we don't want 2 errors printing out */
1238                 return CLI_SUCCESS;
1239         }
1240
1241         if (!strcasecmp(a->argv[1], "start")) {
1242                 mixmonitor_exec(chan, (a->argc >= 4) ? a->argv[3] : "");
1243         } else if (!strcasecmp(a->argv[1], "stop")){
1244                 stop_mixmonitor_exec(chan, (a->argc >= 4) ? a->argv[3] : "");
1245         } else if (!strcasecmp(a->argv[1], "list")) {
1246                 ast_cli(a->fd, "MixMonitor ID\tFile\tReceive File\tTransmit File\n");
1247                 ast_cli(a->fd, "=========================================================================\n");
1248                 ast_channel_lock(chan);
1249                 AST_LIST_TRAVERSE(ast_channel_datastores(chan), datastore, entry) {
1250                         if (datastore->info == &mixmonitor_ds_info) {
1251                                 char *filename = "";
1252                                 char *filename_read = "";
1253                                 char *filename_write = "";
1254
1255                                 mixmonitor_ds = datastore->data;
1256                                 if (mixmonitor_ds->fs) {
1257                                         filename = mixmonitor_ds->fs->filename;
1258                                 }
1259                                 if (mixmonitor_ds->fs_read) {
1260                                         filename_read = mixmonitor_ds->fs_read->filename;
1261                                 }
1262                                 if (mixmonitor_ds->fs_write) {
1263                                         filename_write = mixmonitor_ds->fs_write->filename;
1264                                 }
1265                                 ast_cli(a->fd, "%p\t%s\t%s\t%s\n", mixmonitor_ds, filename, filename_read, filename_write);
1266                         }
1267                 }
1268                 ast_channel_unlock(chan);
1269         } else {
1270                 chan = ast_channel_unref(chan);
1271                 return CLI_SHOWUSAGE;
1272         }
1273
1274         chan = ast_channel_unref(chan);
1275
1276         return CLI_SUCCESS;
1277 }
1278
1279 /*! \brief  Mute / unmute  a MixMonitor channel */
1280 static int manager_mute_mixmonitor(struct mansession *s, const struct message *m)
1281 {
1282         struct ast_channel *c;
1283         const char *name = astman_get_header(m, "Channel");
1284         const char *id = astman_get_header(m, "ActionID");
1285         const char *state = astman_get_header(m, "State");
1286         const char *direction = astman_get_header(m,"Direction");
1287         int clearmute = 1;
1288         enum ast_audiohook_flags flag;
1289
1290         if (ast_strlen_zero(direction)) {
1291                 astman_send_error(s, m, "No direction specified. Must be read, write or both");
1292                 return AMI_SUCCESS;
1293         }
1294
1295         if (!strcasecmp(direction, "read")) {
1296                 flag = AST_AUDIOHOOK_MUTE_READ;
1297         } else  if (!strcasecmp(direction, "write")) {
1298                 flag = AST_AUDIOHOOK_MUTE_WRITE;
1299         } else  if (!strcasecmp(direction, "both")) {
1300                 flag = AST_AUDIOHOOK_MUTE_READ | AST_AUDIOHOOK_MUTE_WRITE;
1301         } else {
1302                 astman_send_error(s, m, "Invalid direction specified. Must be read, write or both");
1303                 return AMI_SUCCESS;
1304         }
1305
1306         if (ast_strlen_zero(name)) {
1307                 astman_send_error(s, m, "No channel specified");
1308                 return AMI_SUCCESS;
1309         }
1310
1311         if (ast_strlen_zero(state)) {
1312                 astman_send_error(s, m, "No state specified");
1313                 return AMI_SUCCESS;
1314         }
1315
1316         clearmute = ast_false(state);
1317
1318         c = ast_channel_get_by_name(name);
1319         if (!c) {
1320                 astman_send_error(s, m, "No such channel");
1321                 return AMI_SUCCESS;
1322         }
1323
1324         if (ast_audiohook_set_mute(c, mixmonitor_spy_type, flag, clearmute)) {
1325                 ast_channel_unref(c);
1326                 astman_send_error(s, m, "Cannot set mute flag");
1327                 return AMI_SUCCESS;
1328         }
1329
1330         astman_append(s, "Response: Success\r\n");
1331
1332         if (!ast_strlen_zero(id)) {
1333                 astman_append(s, "ActionID: %s\r\n", id);
1334         }
1335
1336         astman_append(s, "\r\n");
1337
1338         ast_channel_unref(c);
1339
1340         return AMI_SUCCESS;
1341 }
1342
1343 static int start_mixmonitor_callback(struct ast_channel *chan, const char *filename, const char *options)
1344 {
1345         char args[PATH_MAX];
1346
1347         if (ast_strlen_zero(options)) {
1348                 snprintf(args, sizeof(args), "%s", filename);
1349         } else {
1350                 snprintf(args, sizeof(args), "%s,%s", filename, options);
1351         }
1352
1353         return mixmonitor_exec(chan, args);
1354 }
1355
1356 static int stop_mixmonitor_callback(struct ast_channel *chan, const char *mixmonitor_id)
1357 {
1358         return stop_mixmonitor_full(chan, mixmonitor_id);
1359 }
1360
1361 static int manager_mixmonitor(struct mansession *s, const struct message *m)
1362 {
1363         struct ast_channel *c;
1364         const char *name = astman_get_header(m, "Channel");
1365         const char *id = astman_get_header(m, "ActionID");
1366         const char *file = astman_get_header(m, "File");
1367         const char *options = astman_get_header(m, "Options");
1368         const char *command = astman_get_header(m, "Command");
1369         char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
1370         struct ast_flags flags = { 0 };
1371         char *uid_channel_var = NULL;
1372         const char *mixmonitor_id = NULL;
1373         int res;
1374         char args[PATH_MAX];
1375
1376         if (ast_strlen_zero(name)) {
1377                 astman_send_error(s, m, "No channel specified");
1378                 return AMI_SUCCESS;
1379         }
1380
1381         c = ast_channel_get_by_name(name);
1382         if (!c) {
1383                 astman_send_error(s, m, "No such channel");
1384                 return AMI_SUCCESS;
1385         }
1386
1387         if (!ast_strlen_zero(options)) {
1388                 ast_app_parse_options(mixmonitor_opts, &flags, opts, ast_strdupa(options));
1389         }
1390
1391         snprintf(args, sizeof(args), "%s,%s,%s", file, options, command);
1392
1393         res = mixmonitor_exec(c, args);
1394
1395         if (ast_test_flag(&flags, MUXFLAG_UID)) {
1396                 uid_channel_var = opts[OPT_ARG_UID];
1397                 ast_channel_lock(c);
1398                 mixmonitor_id = pbx_builtin_getvar_helper(c, uid_channel_var);
1399                 mixmonitor_id = ast_strdupa(S_OR(mixmonitor_id, ""));
1400                 ast_channel_unlock(c);
1401         }
1402
1403         if (res) {
1404                 ast_channel_unref(c);
1405                 astman_send_error(s, m, "Could not start monitoring channel");
1406                 return AMI_SUCCESS;
1407         }
1408
1409         astman_append(s, "Response: Success\r\n");
1410
1411         if (!ast_strlen_zero(id)) {
1412                 astman_append(s, "ActionID: %s\r\n", id);
1413         }
1414
1415         if (!ast_strlen_zero(mixmonitor_id)) {
1416                 astman_append(s, "MixMonitorID: %s\r\n", mixmonitor_id);
1417         }
1418
1419         astman_append(s, "\r\n");
1420
1421         ast_channel_unref(c);
1422
1423         return AMI_SUCCESS;
1424 }
1425
1426 static int manager_stop_mixmonitor(struct mansession *s, const struct message *m)
1427 {
1428         struct ast_channel *c;
1429         const char *name = astman_get_header(m, "Channel");
1430         const char *id = astman_get_header(m, "ActionID");
1431         const char *mixmonitor_id = astman_get_header(m, "MixMonitorID");
1432         int res;
1433
1434         if (ast_strlen_zero(name)) {
1435                 astman_send_error(s, m, "No channel specified");
1436                 return AMI_SUCCESS;
1437         }
1438
1439         c = ast_channel_get_by_name(name);
1440         if (!c) {
1441                 astman_send_error(s, m, "No such channel");
1442                 return AMI_SUCCESS;
1443         }
1444
1445         res = stop_mixmonitor_full(c, mixmonitor_id);
1446         if (res) {
1447                 ast_channel_unref(c);
1448                 astman_send_error(s, m, "Could not stop monitoring channel");
1449                 return AMI_SUCCESS;
1450         }
1451
1452         astman_append(s, "Response: Success\r\n");
1453
1454         if (!ast_strlen_zero(id)) {
1455                 astman_append(s, "ActionID: %s\r\n", id);
1456         }
1457
1458         astman_append(s, "\r\n");
1459
1460         ast_channel_unref(c);
1461
1462         return AMI_SUCCESS;
1463 }
1464
1465 static int func_mixmonitor_read(struct ast_channel *chan, const char *cmd, char *data,
1466                 char *buf, size_t len)
1467 {
1468         struct ast_datastore *datastore;
1469         struct mixmonitor_ds *ds_data;
1470         AST_DECLARE_APP_ARGS(args,
1471                 AST_APP_ARG(id);
1472                 AST_APP_ARG(key);
1473         );
1474
1475         AST_STANDARD_APP_ARGS(args, data);
1476
1477         if (ast_strlen_zero(args.id) || ast_strlen_zero(args.key)) {
1478                 ast_log(LOG_WARNING, "Not enough arguments provided to %s. "
1479                                 "An ID and key must be provided\n", cmd);
1480                 return -1;
1481         }
1482
1483         ast_channel_lock(chan);
1484         datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info, args.id);
1485         ast_channel_unlock(chan);
1486
1487         if (!datastore) {
1488                 ast_log(LOG_WARNING, "Could not find MixMonitor with ID %s\n", args.id);
1489                 return -1;
1490         }
1491
1492         ds_data = datastore->data;
1493
1494         if (!strcasecmp(args.key, "filename")) {
1495                 ast_copy_string(buf, ds_data->filename, len);
1496         } else {
1497                 ast_log(LOG_WARNING, "Unrecognized %s option %s\n", cmd, args.key);
1498                 return -1;
1499         }
1500         return 0;
1501 }
1502
1503 static struct ast_custom_function mixmonitor_function = {
1504         .name = "MIXMONITOR",
1505         .read = func_mixmonitor_read,
1506 };
1507
1508 static struct ast_cli_entry cli_mixmonitor[] = {
1509         AST_CLI_DEFINE(handle_cli_mixmonitor, "Execute a MixMonitor command")
1510 };
1511
1512 static int set_mixmonitor_methods(void)
1513 {
1514         struct ast_mixmonitor_methods mixmonitor_methods = {
1515                 .start = start_mixmonitor_callback,
1516                 .stop = stop_mixmonitor_callback,
1517         };
1518
1519         return ast_set_mixmonitor_methods(&mixmonitor_methods);
1520 }
1521
1522 static int clear_mixmonitor_methods(void)
1523 {
1524         return ast_clear_mixmonitor_methods();
1525 }
1526
1527 static int unload_module(void)
1528 {
1529         int res;
1530
1531         ast_cli_unregister_multiple(cli_mixmonitor, ARRAY_LEN(cli_mixmonitor));
1532         res = ast_unregister_application(stop_app);
1533         res |= ast_unregister_application(app);
1534         res |= ast_manager_unregister("MixMonitorMute");
1535         res |= ast_manager_unregister("MixMonitor");
1536         res |= ast_manager_unregister("StopMixMonitor");
1537         res |= ast_custom_function_unregister(&mixmonitor_function);
1538         res |= clear_mixmonitor_methods();
1539
1540         return res;
1541 }
1542
1543 static int load_module(void)
1544 {
1545         int res;
1546
1547         ast_cli_register_multiple(cli_mixmonitor, ARRAY_LEN(cli_mixmonitor));
1548         res = ast_register_application_xml(app, mixmonitor_exec);
1549         res |= ast_register_application_xml(stop_app, stop_mixmonitor_exec);
1550         res |= ast_manager_register_xml("MixMonitorMute", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, manager_mute_mixmonitor);
1551         res |= ast_manager_register_xml("MixMonitor", EVENT_FLAG_SYSTEM, manager_mixmonitor);
1552         res |= ast_manager_register_xml("StopMixMonitor", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, manager_stop_mixmonitor);
1553         res |= ast_custom_function_register(&mixmonitor_function);
1554         res |= set_mixmonitor_methods();
1555
1556         return res;
1557 }
1558
1559 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Mixed Audio Monitoring Application",
1560         .support_level = AST_MODULE_SUPPORT_CORE,
1561         .load = load_module,
1562         .unload = unload_module,
1563         .optional_modules = "func_periodic_hook",
1564 );