bridge_channel_write_frame: Check for NULL channel
[asterisk/asterisk.git] / res / res_musiconhold.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2010, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Routines implementing music on hold
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25
26 /*! \li \ref res_musiconhold.c uses the configuration file \ref musiconhold.conf
27  * \addtogroup configuration_file Configuration Files
28  */
29
30 /*!
31  * \page musiconhold.conf musiconhold.conf
32  * \verbinclude musiconhold.conf.sample
33  */
34
35 /*** MODULEINFO
36         <conflict>win32</conflict>
37         <support_level>core</support_level>
38  ***/
39
40 #include "asterisk.h"
41
42 #include <ctype.h>
43 #include <signal.h>
44 #include <sys/time.h>
45 #include <signal.h>
46 #include <netinet/in.h>
47 #include <sys/stat.h>
48 #include <dirent.h>
49
50 #ifdef SOLARIS
51 #include <thread.h>
52 #endif
53
54 #include "asterisk/lock.h"
55 #include "asterisk/file.h"
56 #include "asterisk/channel.h"
57 #include "asterisk/pbx.h"
58 #include "asterisk/app.h"
59 #include "asterisk/module.h"
60 #include "asterisk/translate.h"
61 #include "asterisk/say.h"
62 #include "asterisk/musiconhold.h"
63 #include "asterisk/config.h"
64 #include "asterisk/utils.h"
65 #include "asterisk/cli.h"
66 #include "asterisk/stringfields.h"
67 #include "asterisk/linkedlists.h"
68 #include "asterisk/stasis.h"
69 #include "asterisk/stasis_channels.h"
70 #include "asterisk/paths.h"
71 #include "asterisk/astobj2.h"
72 #include "asterisk/timing.h"
73 #include "asterisk/time.h"
74 #include "asterisk/poll-compat.h"
75
76 #define INITIAL_NUM_FILES   8
77 #define HANDLE_REF      1
78 #define DONT_UNREF      0
79
80 /*** DOCUMENTATION
81         <application name="MusicOnHold" language="en_US">
82                 <synopsis>
83                         Play Music On Hold indefinitely.
84                 </synopsis>
85                 <syntax>
86                         <parameter name="class" required="true" />
87                         <parameter name="duration" />
88                 </syntax>
89                 <description>
90                         <para>Plays hold music specified by class. If omitted, the default music
91                         source for the channel will be used. Change the default class with
92                         Set(CHANNEL(musicclass)=...). If duration is given, hold music will be played
93                         specified number of seconds. If duration is ommited, music plays indefinitely.
94                         Returns <literal>0</literal> when done, <literal>-1</literal> on hangup.</para>
95                         <para>This application does not automatically answer and should be preceeded by
96                         an application such as Answer() or Progress().</para>
97                 </description>
98         </application>
99         <application name="StartMusicOnHold" language="en_US">
100                 <synopsis>
101                         Play Music On Hold.
102                 </synopsis>
103                 <syntax>
104                         <parameter name="class" required="true" />
105                 </syntax>
106                 <description>
107                         <para>Starts playing music on hold, uses default music class for channel.
108                         Starts playing music specified by class. If omitted, the default music
109                         source for the channel will be used. Always returns <literal>0</literal>.</para>
110                 </description>
111         </application>
112         <application name="StopMusicOnHold" language="en_US">
113                 <synopsis>
114                         Stop playing Music On Hold.
115                 </synopsis>
116                 <syntax />
117                 <description>
118                         <para>Stops playing music on hold.</para>
119                 </description>
120         </application>
121  ***/
122
123 static const char play_moh[] = "MusicOnHold";
124 static const char start_moh[] = "StartMusicOnHold";
125 static const char stop_moh[] = "StopMusicOnHold";
126
127 static int respawn_time = 20;
128
129 struct moh_files_state {
130         /*! Holds a reference to the MOH class. */
131         struct mohclass *class;
132         struct ast_format *origwfmt;
133         struct ast_format *mohwfmt;
134         int announcement;
135         int samples;
136         int sample_queue;
137         int pos;
138         int save_pos;
139         int save_total;
140         char name[MAX_MUSICCLASS];
141         char save_pos_filename[PATH_MAX];
142 };
143
144 #define MOH_QUIET               (1 << 0)
145 #define MOH_SINGLE              (1 << 1)
146 #define MOH_CUSTOM              (1 << 2)
147 #define MOH_RANDOMIZE           (1 << 3)
148 #define MOH_SORTALPHA           (1 << 4)
149 #define MOH_RANDSTART           (MOH_RANDOMIZE | MOH_SORTALPHA) /*!< Sorted but start at random position */
150 #define MOH_SORTMODE            (3 << 3)
151
152 #define MOH_CACHERTCLASSES      (1 << 5)        /*!< Should we use a separate instance of MOH for each user or not */
153 #define MOH_ANNOUNCEMENT        (1 << 6)        /*!< Do we play announcement files between songs on this channel? */
154 #define MOH_PREFERCHANNELCLASS  (1 << 7)        /*!< Should queue moh override channel moh */
155
156 /* Custom astobj2 flag */
157 #define MOH_NOTDELETED          (1 << 30)       /*!< Find only records that aren't deleted? */
158 #define MOH_REALTIME          (1 << 31)       /*!< Find only records that are realtime */
159
160 static struct ast_flags global_flags[1] = {{0}};        /*!< global MOH_ flags */
161
162 enum kill_methods {
163         KILL_METHOD_PROCESS_GROUP = 0,
164         KILL_METHOD_PROCESS
165 };
166
167 struct mohclass {
168         char name[MAX_MUSICCLASS];
169         char dir[256];
170         char args[256];
171         char announcement[256];
172         char mode[80];
173         char digit;
174         /*! An immutable vector of filenames in "files" mode */
175         struct ast_vector_string *files;
176         unsigned int flags;
177         /*! The format from the MOH source, not applicable to "files" mode */
178         struct ast_format *format;
179         /*! The pid of the external application delivering MOH */
180         int pid;
181         time_t start;
182         pthread_t thread;
183         /*! Millisecond delay between kill attempts */
184         size_t kill_delay;
185         /*! Kill method */
186         enum kill_methods kill_method;
187         /*! Source of audio */
188         int srcfd;
189         /*! Generic timer */
190         struct ast_timer *timer;
191         /*! Created on the fly, from RT engine */
192         unsigned int realtime:1;
193         unsigned int delete:1;
194         AST_LIST_HEAD_NOLOCK(, mohdata) members;
195         AST_LIST_ENTRY(mohclass) list;
196 };
197
198 struct mohdata {
199         int pipe[2];
200         struct ast_format *origwfmt;
201         struct mohclass *parent;
202         struct ast_frame f;
203         AST_LIST_ENTRY(mohdata) list;
204 };
205
206 static struct ao2_container *mohclasses;
207
208 #define LOCAL_MPG_123 "/usr/local/bin/mpg123"
209 #define MPG_123 "/usr/bin/mpg123"
210 #define MAX_MP3S 256
211
212 static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclass);
213 static int reload(void);
214
215 #define mohclass_ref(class,string)   (ao2_t_ref((class), +1, (string)), class)
216
217 #ifndef AST_DEVMODE
218 #define mohclass_unref(class,string) ({ ao2_t_ref((class), -1, (string)); (struct mohclass *) NULL; })
219 #else
220 #define mohclass_unref(class,string) _mohclass_unref(class, string, __FILE__,__LINE__,__PRETTY_FUNCTION__)
221 static struct mohclass *_mohclass_unref(struct mohclass *class, const char *tag, const char *file, int line, const char *funcname)
222 {
223         struct mohclass *dup = ao2_callback(mohclasses, OBJ_POINTER, ao2_match_by_addr, class);
224
225         if (dup) {
226                 if (__ao2_ref(dup, -1, tag, file, line, funcname) == 2) {
227                         ast_log(LOG_WARNING, "Attempt to unref mohclass %p (%s) when only 1 ref remained, and class is still in a container! (at %s:%d (%s))\n",
228                                 class, class->name, file, line, funcname);
229                 } else {
230                         ao2_ref(class, -1);
231                 }
232         } else {
233                 __ao2_ref(class, -1, tag, file, line, funcname);
234         }
235         return NULL;
236 }
237 #endif
238
239 static void moh_post_start(struct ast_channel *chan, const char *moh_class_name)
240 {
241         struct stasis_message *message;
242         struct ast_json *json_object;
243
244         ast_verb(3, "Started music on hold, class '%s', on channel '%s'\n",
245                 moh_class_name, ast_channel_name(chan));
246
247         json_object = ast_json_pack("{s: s}", "class", moh_class_name);
248         if (!json_object) {
249                 return;
250         }
251
252         message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan),
253                 ast_channel_moh_start_type(), json_object);
254         if (message) {
255                 /* A channel snapshot must have been in the cache. */
256                 ast_assert(((struct ast_channel_blob *) stasis_message_data(message))->snapshot != NULL);
257
258                 stasis_publish(ast_channel_topic(chan), message);
259         }
260         ao2_cleanup(message);
261         ast_json_unref(json_object);
262 }
263
264 static void moh_post_stop(struct ast_channel *chan)
265 {
266         struct stasis_message *message;
267
268         ast_verb(3, "Stopped music on hold on %s\n", ast_channel_name(chan));
269
270         message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan),
271                 ast_channel_moh_stop_type(), NULL);
272         if (message) {
273                 /* A channel snapshot must have been in the cache. */
274                 ast_assert(((struct ast_channel_blob *) stasis_message_data(message))->snapshot != NULL);
275
276                 stasis_publish(ast_channel_topic(chan), message);
277         }
278         ao2_cleanup(message);
279 }
280
281 static void moh_files_release(struct ast_channel *chan, void *data)
282 {
283         struct moh_files_state *state;
284
285         if (!chan || !ast_channel_music_state(chan)) {
286                 return;
287         }
288
289         state = ast_channel_music_state(chan);
290
291         if (ast_channel_stream(chan)) {
292                 ast_closestream(ast_channel_stream(chan));
293                 ast_channel_stream_set(chan, NULL);
294         }
295
296         moh_post_stop(chan);
297
298         ao2_ref(state->mohwfmt, -1);
299         state->mohwfmt = NULL; /* make sure to clear this format before restoring the original format */
300         if (state->origwfmt && ast_set_write_format(chan, state->origwfmt)) {
301                 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n", ast_channel_name(chan),
302                         ast_format_get_name(state->origwfmt));
303         }
304         ao2_cleanup(state->origwfmt);
305         state->origwfmt = NULL;
306
307         state->save_pos = state->pos;
308         state->announcement = 0;
309
310         state->class = mohclass_unref(state->class, "Unreffing channel's music class upon deactivation of generator");
311 }
312
313 static int ast_moh_files_next(struct ast_channel *chan)
314 {
315         struct moh_files_state *state = ast_channel_music_state(chan);
316         struct ast_vector_string *files;
317         int tries;
318         size_t file_count;
319
320         /* Discontinue a stream if it is running already */
321         if (ast_channel_stream(chan)) {
322                 ast_closestream(ast_channel_stream(chan));
323                 ast_channel_stream_set(chan, NULL);
324         }
325
326         if (ast_test_flag(state->class, MOH_ANNOUNCEMENT) && state->announcement == 0) {
327                 state->announcement = 1;
328                 if (ast_openstream_full(chan, state->class->announcement, ast_channel_language(chan), 1)) {
329                         ast_debug(1, "%s Opened announcement '%s'\n", ast_channel_name(chan), state->class->announcement);
330                         return 0;
331                 }
332         } else {
333                 state->announcement = 0;
334         }
335
336         ao2_lock(state->class);
337         files = ao2_bump(state->class->files);
338         ao2_unlock(state->class);
339
340         file_count = AST_VECTOR_SIZE(files);
341         if (!file_count) {
342                 ast_log(LOG_WARNING, "No files available for class '%s'\n", state->class->name);
343                 ao2_ref(files, -1);
344                 return -1;
345         }
346
347         if (state->pos == 0 && ast_strlen_zero(state->save_pos_filename)) {
348                 /* First time so lets play the file. */
349                 state->save_pos = -1;
350         } else if (state->save_pos >= 0 && state->save_pos < file_count && !strcmp(AST_VECTOR_GET(files, state->save_pos), state->save_pos_filename)) {
351                 /* If a specific file has been saved confirm it still exists and that it is still valid */
352                 state->pos = state->save_pos;
353                 state->save_pos = -1;
354         } else if (ast_test_flag(state->class, MOH_SORTMODE) == MOH_RANDOMIZE) {
355                 /* Get a random file and ensure we can open it */
356                 for (tries = 0; tries < 20; tries++) {
357                         state->pos = ast_random() % file_count;
358                         if (ast_fileexists(AST_VECTOR_GET(files, state->pos), NULL, NULL) > 0) {
359                                 break;
360                         }
361                 }
362                 state->save_pos = -1;
363                 state->samples = 0;
364         } else {
365                 /* This is easy, just increment our position and make sure we don't exceed the total file count */
366                 state->pos++;
367                 state->pos %= file_count;
368                 state->save_pos = -1;
369                 state->samples = 0;
370         }
371
372         for (tries = 0; tries < file_count; ++tries) {
373                 if (ast_openstream_full(chan, AST_VECTOR_GET(files, state->pos), ast_channel_language(chan), 1)) {
374                         break;
375                 }
376
377                 ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", AST_VECTOR_GET(files, state->pos), strerror(errno));
378                 state->pos++;
379                 state->pos %= file_count;
380         }
381
382         if (tries == file_count) {
383                 ao2_ref(files, -1);
384                 return -1;
385         }
386
387         /* Record the pointer to the filename for position resuming later */
388         ast_copy_string(state->save_pos_filename, AST_VECTOR_GET(files, state->pos), sizeof(state->save_pos_filename));
389
390         ast_debug(1, "%s Opened file %d '%s'\n", ast_channel_name(chan), state->pos, state->save_pos_filename);
391
392         if (state->samples) {
393                 size_t loc;
394                 /* seek *SHOULD* be good since it's from a known location */
395                 ast_seekstream(ast_channel_stream(chan), state->samples, SEEK_SET);
396                 /* if the seek failed then recover because if there is not a valid read,
397                  * moh_files_generate will return -1 and MOH will stop */
398                 loc = ast_tellstream(ast_channel_stream(chan));
399                 if (state->samples > loc && loc) {
400                         /* seek one sample from the end for one guaranteed valid read */
401                         ast_seekstream(ast_channel_stream(chan), 1, SEEK_END);
402                 }
403         }
404
405         ao2_ref(files, -1);
406         return 0;
407 }
408
409 static struct ast_frame *moh_files_readframe(struct ast_channel *chan)
410 {
411         struct ast_frame *f;
412
413         f = ast_readframe(ast_channel_stream(chan));
414         if (!f) {
415                 /* Either there was no file stream setup or we reached EOF. */
416                 if (!ast_moh_files_next(chan)) {
417                         /*
418                          * Either we resetup the previously saved file stream position
419                          * or we started a new file stream.
420                          */
421                         f = ast_readframe(ast_channel_stream(chan));
422                         if (!f) {
423                                 /*
424                                  * We can get here if we were very unlucky because the
425                                  * resetup file stream was saved at EOF when MOH was
426                                  * previously stopped.
427                                  */
428                                 if (!ast_moh_files_next(chan)) {
429                                         f = ast_readframe(ast_channel_stream(chan));
430                                 }
431                         }
432                 }
433         }
434
435         return f;
436 }
437
438 static void moh_files_write_format_change(struct ast_channel *chan, void *data)
439 {
440         struct moh_files_state *state = ast_channel_music_state(chan);
441
442         /* In order to prevent a recursive call to this function as a result
443          * of setting the moh write format back on the channel. Clear
444          * the moh write format before setting the write format on the channel.*/
445         if (state->origwfmt) {
446                 struct ast_format *tmp;
447
448                 tmp = ao2_bump(ast_channel_writeformat(chan));
449                 ao2_replace(state->origwfmt, NULL);
450                 if (state->mohwfmt) {
451                         ast_set_write_format(chan, state->mohwfmt);
452                 }
453                 state->origwfmt = tmp;
454         }
455 }
456
457 static int moh_files_generator(struct ast_channel *chan, void *data, int len, int samples)
458 {
459         struct moh_files_state *state = ast_channel_music_state(chan);
460         struct ast_frame *f = NULL;
461         int res = 0;
462
463         state->sample_queue += samples;
464
465         while (state->sample_queue > 0) {
466                 ast_channel_lock(chan);
467                 f = moh_files_readframe(chan);
468
469                 /* We need to be sure that we unlock
470                  * the channel prior to calling
471                  * ast_write. Otherwise, the recursive locking
472                  * that occurs can cause deadlocks when using
473                  * indirect channels, like local channels
474                  */
475                 ast_channel_unlock(chan);
476                 if (!f) {
477                         return -1;
478                 }
479
480                 /* Only track our offset within the current file if we are not in the
481                  * the middle of an announcement */
482                 if (!state->announcement) {
483                         state->samples += f->samples;
484                 }
485
486                 state->sample_queue -= f->samples;
487                 if (ast_format_cmp(f->subclass.format, state->mohwfmt) == AST_FORMAT_CMP_NOT_EQUAL) {
488                         ao2_replace(state->mohwfmt, f->subclass.format);
489                 }
490                 res = ast_write(chan, f);
491                 ast_frfree(f);
492                 if (res < 0) {
493                         ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
494                         return -1;
495                 }
496         }
497         return res;
498 }
499
500 static void *moh_files_alloc(struct ast_channel *chan, void *params)
501 {
502         struct moh_files_state *state;
503         struct mohclass *class = params;
504         size_t file_count;
505
506         state = ast_channel_music_state(chan);
507         if (!state && (state = ast_calloc(1, sizeof(*state)))) {
508                 ast_channel_music_state_set(chan, state);
509                 ast_module_ref(ast_module_info->self);
510         } else {
511                 if (!state) {
512                         return NULL;
513                 }
514                 if (state->class) {
515                         mohclass_unref(state->class, "Uh Oh. Restarting MOH with an active class");
516                         ast_log(LOG_WARNING, "Uh Oh. Restarting MOH with an active class\n");
517                 }
518         }
519
520         ao2_lock(class);
521         file_count = AST_VECTOR_SIZE(class->files);
522         ao2_unlock(class);
523
524         /* Resume MOH from where we left off last time or start from scratch? */
525         if (state->save_total != file_count || strcmp(state->name, class->name) != 0) {
526                 /* Start MOH from scratch. */
527                 ao2_cleanup(state->origwfmt);
528                 ao2_cleanup(state->mohwfmt);
529                 memset(state, 0, sizeof(*state));
530                 if (ast_test_flag(class, MOH_RANDOMIZE) && file_count) {
531                         state->pos = ast_random() % file_count;
532                 }
533         }
534
535         state->class = mohclass_ref(class, "Reffing music class for channel");
536         /* it's possible state is not a new allocation, don't leak old refs */
537         ao2_replace(state->origwfmt, ast_channel_writeformat(chan));
538         ao2_replace(state->mohwfmt, ast_channel_writeformat(chan));
539         /* For comparison on restart of MOH (see above) */
540         ast_copy_string(state->name, class->name, sizeof(state->name));
541         state->save_total = file_count;
542
543         moh_post_start(chan, class->name);
544
545         return state;
546 }
547
548 static int moh_digit_match(void *obj, void *arg, int flags)
549 {
550         char *digit = arg;
551         struct mohclass *class = obj;
552
553         return (*digit == class->digit) ? CMP_MATCH | CMP_STOP : 0;
554 }
555
556 /*! \note This function should be called with the mohclasses list locked */
557 static struct mohclass *get_mohbydigit(char digit)
558 {
559         return ao2_t_callback(mohclasses, 0, moh_digit_match, &digit, "digit callback");
560 }
561
562 static void moh_handle_digit(struct ast_channel *chan, char digit)
563 {
564         struct mohclass *class;
565         const char *classname = NULL;
566
567         if ((class = get_mohbydigit(digit))) {
568                 classname = ast_strdupa(class->name);
569                 class = mohclass_unref(class, "Unreffing ao2_find from finding by digit");
570                 ast_channel_musicclass_set(chan, classname);
571                 ast_moh_stop(chan);
572                 ast_moh_start(chan, classname, NULL);
573         }
574 }
575
576 static struct ast_generator moh_file_stream = {
577         .alloc    = moh_files_alloc,
578         .release  = moh_files_release,
579         .generate = moh_files_generator,
580         .digit    = moh_handle_digit,
581         .write_format_change = moh_files_write_format_change,
582 };
583
584 static int spawn_mp3(struct mohclass *class)
585 {
586         int fds[2];
587         int files = 0;
588         char fns[MAX_MP3S][80];
589         char *argv[MAX_MP3S + 50];
590         char xargs[256];
591         char *argptr;
592         int argc = 0;
593         DIR *dir = NULL;
594         struct dirent *de;
595
596
597         if (!strcasecmp(class->dir, "nodir")) {
598                 files = 1;
599         } else {
600                 dir = opendir(class->dir);
601                 if (!dir && strncasecmp(class->dir, "http://", 7)) {
602                         ast_log(LOG_WARNING, "%s is not a valid directory\n", class->dir);
603                         return -1;
604                 }
605         }
606
607         if (!ast_test_flag(class, MOH_CUSTOM)) {
608                 argv[argc++] = "mpg123";
609                 argv[argc++] = "-q";
610                 argv[argc++] = "-s";
611                 argv[argc++] = "--mono";
612                 argv[argc++] = "-r";
613                 argv[argc++] = "8000";
614
615                 if (!ast_test_flag(class, MOH_SINGLE)) {
616                         argv[argc++] = "-b";
617                         argv[argc++] = "2048";
618                 }
619
620                 argv[argc++] = "-f";
621
622                 if (ast_test_flag(class, MOH_QUIET))
623                         argv[argc++] = "4096";
624                 else
625                         argv[argc++] = "8192";
626
627                 /* Look for extra arguments and add them to the list */
628                 ast_copy_string(xargs, class->args, sizeof(xargs));
629                 argptr = xargs;
630                 while (!ast_strlen_zero(argptr)) {
631                         argv[argc++] = argptr;
632                         strsep(&argptr, ",");
633                 }
634         } else  {
635                 /* Format arguments for argv vector */
636                 ast_copy_string(xargs, class->args, sizeof(xargs));
637                 argptr = xargs;
638                 while (!ast_strlen_zero(argptr)) {
639                         argv[argc++] = argptr;
640                         strsep(&argptr, " ");
641                 }
642         }
643
644         if (!strncasecmp(class->dir, "http://", 7)) {
645                 ast_copy_string(fns[files], class->dir, sizeof(fns[files]));
646                 argv[argc++] = fns[files];
647                 files++;
648         } else if (dir) {
649                 while ((de = readdir(dir)) && (files < MAX_MP3S)) {
650                         if ((strlen(de->d_name) > 3) &&
651                             ((ast_test_flag(class, MOH_CUSTOM) &&
652                               (!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".raw") ||
653                                !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".sln"))) ||
654                              !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3"))) {
655                                 ast_copy_string(fns[files], de->d_name, sizeof(fns[files]));
656                                 argv[argc++] = fns[files];
657                                 files++;
658                         }
659                 }
660         }
661         argv[argc] = NULL;
662         if (dir) {
663                 closedir(dir);
664         }
665         if (pipe(fds)) {
666                 ast_log(LOG_WARNING, "Pipe failed\n");
667                 return -1;
668         }
669         if (!files) {
670                 ast_log(LOG_WARNING, "Found no files in '%s'\n", class->dir);
671                 close(fds[0]);
672                 close(fds[1]);
673                 return -1;
674         }
675         if (!strncasecmp(class->dir, "http://", 7) && time(NULL) - class->start < respawn_time) {
676                 sleep(respawn_time - (time(NULL) - class->start));
677         }
678
679         time(&class->start);
680         class->pid = ast_safe_fork(0);
681         if (class->pid < 0) {
682                 close(fds[0]);
683                 close(fds[1]);
684                 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
685                 return -1;
686         }
687         if (!class->pid) {
688                 if (ast_opt_high_priority)
689                         ast_set_priority(0);
690
691                 close(fds[0]);
692                 /* Stdout goes to pipe */
693                 dup2(fds[1], STDOUT_FILENO);
694
695                 /* Close everything else */
696                 ast_close_fds_above_n(STDERR_FILENO);
697
698                 /* Child */
699                 if (strncasecmp(class->dir, "http://", 7) && strcasecmp(class->dir, "nodir") && chdir(class->dir) < 0) {
700                         ast_log(LOG_WARNING, "chdir() failed: %s\n", strerror(errno));
701                         _exit(1);
702                 }
703                 setpgid(0, getpid());
704                 if (ast_test_flag(class, MOH_CUSTOM)) {
705                         execv(argv[0], argv);
706                 } else {
707                         /* Default install is /usr/local/bin */
708                         execv(LOCAL_MPG_123, argv);
709                         /* Many places have it in /usr/bin */
710                         execv(MPG_123, argv);
711                         /* Check PATH as a last-ditch effort */
712                         execvp("mpg123", argv);
713                 }
714                 /* Can't use logger, since log FDs are closed */
715                 fprintf(stderr, "MOH: exec failed: %s\n", strerror(errno));
716                 close(fds[1]);
717                 _exit(1);
718         } else {
719                 /* Parent */
720                 close(fds[1]);
721         }
722         return fds[0];
723 }
724
725 static int killer(pid_t pid, int signum, enum kill_methods kill_method)
726 {
727         switch (kill_method) {
728         case KILL_METHOD_PROCESS_GROUP:
729                 return killpg(pid, signum);
730         case KILL_METHOD_PROCESS:
731                 return kill(pid, signum);
732         }
733
734         return -1;
735 }
736
737 static void killpid(int pid, size_t delay, enum kill_methods kill_method)
738 {
739         if (killer(pid, SIGHUP, kill_method) < 0) {
740                 if (errno == ESRCH) {
741                         return;
742                 }
743                 ast_log(LOG_WARNING, "Unable to send a SIGHUP to MOH process '%d'?!!: %s\n", pid, strerror(errno));
744         } else {
745                 ast_debug(1, "Sent HUP to pid %d%s\n", pid,
746                         kill_method == KILL_METHOD_PROCESS_GROUP ? " and all children" : " only");
747         }
748         usleep(delay);
749         if (killer(pid, SIGTERM, kill_method) < 0) {
750                 if (errno == ESRCH) {
751                         return;
752                 }
753                 ast_log(LOG_WARNING, "Unable to terminate MOH process '%d'?!!: %s\n", pid, strerror(errno));
754         } else {
755                 ast_debug(1, "Sent TERM to pid %d%s\n", pid,
756                         kill_method == KILL_METHOD_PROCESS_GROUP ? " and all children" : " only");
757         }
758         usleep(delay);
759         if (killer(pid, SIGKILL, kill_method) < 0) {
760                 if (errno == ESRCH) {
761                         return;
762                 }
763                 ast_log(LOG_WARNING, "Unable to kill MOH process '%d'?!!: %s\n", pid, strerror(errno));
764         } else {
765                 ast_debug(1, "Sent KILL to pid %d%s\n", pid,
766                         kill_method == KILL_METHOD_PROCESS_GROUP ? " and all children" : " only");
767         }
768 }
769
770 static void *monmp3thread(void *data)
771 {
772 #define MOH_MS_INTERVAL         100
773
774         struct mohclass *class = data;
775         struct mohdata *moh;
776         short sbuf[8192];
777         int res = 0, res2;
778         int len;
779         struct timeval deadline, tv_tmp;
780
781         deadline.tv_sec = 0;
782         deadline.tv_usec = 0;
783         for(;/* ever */;) {
784                 pthread_testcancel();
785                 /* Spawn mp3 player if it's not there */
786                 if (class->srcfd < 0) {
787                         if ((class->srcfd = spawn_mp3(class)) < 0) {
788                                 ast_log(LOG_WARNING, "Unable to spawn mp3player\n");
789                                 /* Try again later */
790                                 sleep(500);
791                                 continue;
792                         }
793                 }
794                 if (class->timer) {
795                         struct pollfd pfd = { .fd = ast_timer_fd(class->timer), .events = POLLIN | POLLPRI, };
796
797 #ifdef SOLARIS
798                         thr_yield();
799 #endif
800                         /* Pause some amount of time */
801                         if (ast_poll(&pfd, 1, -1) > 0) {
802                                 if (ast_timer_ack(class->timer, 1) < 0) {
803                                         ast_log(LOG_ERROR, "Failed to acknowledge timer for mp3player\n");
804                                         return NULL;
805                                 }
806                                 /* 25 samples per second => 40ms framerate => 320 samples */
807                                 res = 320; /* 320/40 = 8 samples/ms */
808                         } else {
809                                 ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
810                                 res = 0;
811                         }
812                         pthread_testcancel();
813                 } else {
814                         long delta;
815                         /* Reliable sleep */
816                         tv_tmp = ast_tvnow();
817                         if (ast_tvzero(deadline))
818                                 deadline = tv_tmp;
819                         delta = ast_tvdiff_ms(tv_tmp, deadline);
820                         if (delta < MOH_MS_INTERVAL) {  /* too early */
821                                 deadline = ast_tvadd(deadline, ast_samp2tv(MOH_MS_INTERVAL, 1000));     /* next deadline */
822                                 usleep(1000 * (MOH_MS_INTERVAL - delta));
823                                 pthread_testcancel();
824                         } else {
825                                 ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
826                                 deadline = tv_tmp;
827                         }
828                         /* 10 samples per second (MOH_MS_INTERVAL) => 100ms framerate => 800 samples */
829                         res = 8 * MOH_MS_INTERVAL; /* 800/100 = 8 samples/ms */
830                 }
831                 /* For non-8000Hz formats, we need to alter the resolution */
832                 res = res * ast_format_get_sample_rate(class->format) / 8000;
833
834                 if ((strncasecmp(class->dir, "http://", 7) && strcasecmp(class->dir, "nodir")) && AST_LIST_EMPTY(&class->members))
835                         continue;
836                 /* Read mp3 audio */
837                 len = ast_format_determine_length(class->format, res);
838
839                 if ((res2 = read(class->srcfd, sbuf, len)) != len) {
840                         if (!res2) {
841                                 close(class->srcfd);
842                                 class->srcfd = -1;
843                                 pthread_testcancel();
844                                 if (class->pid > 1) {
845                                         killpid(class->pid, class->kill_delay, class->kill_method);
846                                         class->pid = 0;
847                                 }
848                         } else {
849                                 ast_debug(1, "Read %d bytes of audio while expecting %d\n", res2, len);
850                         }
851                         continue;
852                 }
853
854                 pthread_testcancel();
855
856                 ao2_lock(class);
857                 AST_LIST_TRAVERSE(&class->members, moh, list) {
858                         /* Write data */
859                         if ((res = write(moh->pipe[1], sbuf, res2)) != res2) {
860                                 ast_debug(1, "Only wrote %d of %d bytes to pipe\n", res, res2);
861                         }
862                 }
863                 ao2_unlock(class);
864         }
865         return NULL;
866 }
867
868 static int play_moh_exec(struct ast_channel *chan, const char *data)
869 {
870         char *parse;
871         char *class;
872         int timeout = -1;
873         int res;
874         AST_DECLARE_APP_ARGS(args,
875                 AST_APP_ARG(class);
876                 AST_APP_ARG(duration);
877         );
878
879         parse = ast_strdupa(data);
880
881         AST_STANDARD_APP_ARGS(args, parse);
882
883         if (!ast_strlen_zero(args.duration)) {
884                 if (sscanf(args.duration, "%30d", &timeout) == 1) {
885                         timeout *= 1000;
886                 } else {
887                         ast_log(LOG_WARNING, "Invalid MusicOnHold duration '%s'. Will wait indefinitely.\n", args.duration);
888                 }
889         }
890
891         class = S_OR(args.class, NULL);
892         if (ast_moh_start(chan, class, NULL)) {
893                 ast_log(LOG_WARNING, "Unable to start music on hold class '%s' on channel %s\n", class, ast_channel_name(chan));
894                 return 0;
895         }
896
897         if (timeout > 0)
898                 res = ast_safe_sleep(chan, timeout);
899         else {
900                 while (!(res = ast_safe_sleep(chan, 10000)));
901         }
902
903         ast_moh_stop(chan);
904
905         return res;
906 }
907
908 static int start_moh_exec(struct ast_channel *chan, const char *data)
909 {
910         char *parse;
911         char *class;
912         AST_DECLARE_APP_ARGS(args,
913                 AST_APP_ARG(class);
914         );
915
916         parse = ast_strdupa(data);
917
918         AST_STANDARD_APP_ARGS(args, parse);
919
920         class = S_OR(args.class, NULL);
921         if (ast_moh_start(chan, class, NULL))
922                 ast_log(LOG_WARNING, "Unable to start music on hold class '%s' on channel %s\n", class, ast_channel_name(chan));
923
924         return 0;
925 }
926
927 static int stop_moh_exec(struct ast_channel *chan, const char *data)
928 {
929         ast_moh_stop(chan);
930
931         return 0;
932 }
933
934 #define get_mohbyname(a,b,c)    _get_mohbyname(a,b,c,__FILE__,__LINE__,__PRETTY_FUNCTION__)
935
936 static struct mohclass *_get_mohbyname(const char *name, int warn, int flags, const char *file, int lineno, const char *funcname)
937 {
938         struct mohclass *moh = NULL;
939         struct mohclass tmp_class = {
940                 .flags = 0,
941         };
942
943         ast_copy_string(tmp_class.name, name, sizeof(tmp_class.name));
944
945         moh = __ao2_find(mohclasses, &tmp_class, flags,
946                 "get_mohbyname", file, lineno, funcname);
947
948         if (!moh && warn) {
949                 ast_log(LOG_WARNING, "Music on Hold class '%s' not found in memory. Verify your configuration.\n", name);
950         }
951
952         return moh;
953 }
954
955 static struct mohdata *mohalloc(struct mohclass *cl)
956 {
957         struct mohdata *moh;
958
959         if (!(moh = ast_calloc(1, sizeof(*moh))))
960                 return NULL;
961
962         if (ast_pipe_nonblock(moh->pipe)) {
963                 ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno));
964                 ast_free(moh);
965                 return NULL;
966         }
967
968         moh->f.frametype = AST_FRAME_VOICE;
969         moh->f.subclass.format = cl->format;
970         moh->f.offset = AST_FRIENDLY_OFFSET;
971
972         moh->parent = mohclass_ref(cl, "Reffing music class for mohdata parent");
973
974         ao2_lock(cl);
975         AST_LIST_INSERT_HEAD(&cl->members, moh, list);
976         ao2_unlock(cl);
977
978         return moh;
979 }
980
981 static void moh_release(struct ast_channel *chan, void *data)
982 {
983         struct mohdata *moh = data;
984         struct mohclass *class = moh->parent;
985         struct ast_format *oldwfmt;
986
987         ao2_lock(class);
988         AST_LIST_REMOVE(&moh->parent->members, moh, list);
989         ao2_unlock(class);
990
991         close(moh->pipe[0]);
992         close(moh->pipe[1]);
993
994         oldwfmt = moh->origwfmt;
995
996         moh->parent = class = mohclass_unref(class, "unreffing moh->parent upon deactivation of generator");
997
998         ast_free(moh);
999
1000         if (chan) {
1001                 struct moh_files_state *state;
1002
1003                 state = ast_channel_music_state(chan);
1004                 if (state && state->class) {
1005                         state->class = mohclass_unref(state->class, "Unreffing channel's music class upon deactivation of generator");
1006                 }
1007                 if (oldwfmt && ast_set_write_format(chan, oldwfmt)) {
1008                         ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n",
1009                                         ast_channel_name(chan), ast_format_get_name(oldwfmt));
1010                 }
1011
1012                 moh_post_stop(chan);
1013         }
1014
1015         ao2_cleanup(oldwfmt);
1016 }
1017
1018 static void *moh_alloc(struct ast_channel *chan, void *params)
1019 {
1020         struct mohdata *res;
1021         struct mohclass *class = params;
1022         struct moh_files_state *state;
1023
1024         /* Initiating music_state for current channel. Channel should know name of moh class */
1025         state = ast_channel_music_state(chan);
1026         if (!state && (state = ast_calloc(1, sizeof(*state)))) {
1027                 ast_channel_music_state_set(chan, state);
1028                 ast_module_ref(ast_module_info->self);
1029         } else {
1030                 if (!state) {
1031                         return NULL;
1032                 }
1033                 if (state->class) {
1034                         mohclass_unref(state->class, "Uh Oh. Restarting MOH with an active class");
1035                         ast_log(LOG_WARNING, "Uh Oh. Restarting MOH with an active class\n");
1036                 }
1037                 ao2_cleanup(state->origwfmt);
1038                 ao2_cleanup(state->mohwfmt);
1039                 memset(state, 0, sizeof(*state));
1040         }
1041
1042         if ((res = mohalloc(class))) {
1043                 res->origwfmt = ao2_bump(ast_channel_writeformat(chan));
1044                 if (ast_set_write_format(chan, class->format)) {
1045                         ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", ast_channel_name(chan),
1046                                 ast_format_get_name(class->format));
1047                         moh_release(NULL, res);
1048                         res = NULL;
1049                 } else {
1050                         state->class = mohclass_ref(class, "Placing reference into state container");
1051                         moh_post_start(chan, class->name);
1052                 }
1053         }
1054         return res;
1055 }
1056
1057 static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
1058 {
1059         struct mohdata *moh = data;
1060         short buf[1280 + AST_FRIENDLY_OFFSET / 2];
1061         int res;
1062
1063         len = ast_format_determine_length(moh->parent->format, samples);
1064
1065         if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
1066                 ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), len, ast_channel_name(chan));
1067                 len = sizeof(buf) - AST_FRIENDLY_OFFSET;
1068         }
1069         res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
1070         if (res <= 0)
1071                 return 0;
1072
1073         moh->f.datalen = res;
1074         moh->f.data.ptr = buf + AST_FRIENDLY_OFFSET / 2;
1075         moh->f.samples = ast_codec_samples_count(&moh->f);
1076
1077         if (ast_write(chan, &moh->f) < 0) {
1078                 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
1079                 return -1;
1080         }
1081
1082         return 0;
1083 }
1084
1085 static struct ast_generator mohgen = {
1086         .alloc    = moh_alloc,
1087         .release  = moh_release,
1088         .generate = moh_generate,
1089         .digit    = moh_handle_digit,
1090 };
1091
1092 static void moh_file_vector_destructor(void *obj)
1093 {
1094         struct ast_vector_string *files = obj;
1095         AST_VECTOR_RESET(files, ast_free);
1096         AST_VECTOR_FREE(files);
1097 }
1098
1099 static struct ast_vector_string *moh_file_vector_alloc(int initial_capacity)
1100 {
1101         struct ast_vector_string *files = ao2_alloc_options(
1102                 sizeof(struct ast_vector_string),
1103                 moh_file_vector_destructor,
1104                 AO2_ALLOC_OPT_LOCK_NOLOCK);
1105         if (files) {
1106                 AST_VECTOR_INIT(files, initial_capacity);
1107         }
1108         return files;
1109 }
1110
1111 static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclass)
1112 {
1113         struct ast_vector_string *playlist_entries = NULL;
1114
1115         for (; var; var = var->next) {
1116                 if (!strcasecmp(var->name, "name")) {
1117                         ast_copy_string(mohclass->name, var->value, sizeof(mohclass->name));
1118                 } else if (!strcasecmp(var->name, "mode")) {
1119                         ast_copy_string(mohclass->mode, var->value, sizeof(mohclass->mode));
1120                 } else if (!strcasecmp(var->name, "entry")) {
1121                         if (ast_begins_with(var->value, "/") || strstr(var->value, "://")) {
1122                                 char *dup;
1123
1124                                 if (!playlist_entries) {
1125                                         playlist_entries = moh_file_vector_alloc(16);
1126                                         if (!playlist_entries) {
1127                                                 continue;
1128                                         }
1129                                 }
1130
1131                                 dup = ast_strdup(var->value);
1132                                 if (!dup) {
1133                                         continue;
1134                                 }
1135
1136                                 if (ast_begins_with(dup, "/")) {
1137                                         char *last_pos_dot = strrchr(dup, '.');
1138                                         char *last_pos_slash = strrchr(dup, '/');
1139                                         if (last_pos_dot && last_pos_dot > last_pos_slash) {
1140                                                 ast_log(LOG_WARNING, "The playlist entry '%s' may include an extension, which could prevent it from playing.\n",
1141                                                         dup);
1142                                         }
1143                                 }
1144
1145                                 AST_VECTOR_APPEND(playlist_entries, dup);
1146                         } else {
1147                                 ast_log(LOG_ERROR, "Playlist entries must be a URL or an absolute path, '%s' provided.\n", var->value);
1148                         }
1149                 } else if (!strcasecmp(var->name, "directory")) {
1150                         ast_copy_string(mohclass->dir, var->value, sizeof(mohclass->dir));
1151                 } else if (!strcasecmp(var->name, "application")) {
1152                         ast_copy_string(mohclass->args, var->value, sizeof(mohclass->args));
1153                 } else if (!strcasecmp(var->name, "announcement")) {
1154                         ast_copy_string(mohclass->announcement, var->value, sizeof(mohclass->announcement));
1155                         ast_set_flag(mohclass, MOH_ANNOUNCEMENT);
1156                 } else if (!strcasecmp(var->name, "digit") && (isdigit(*var->value) || strchr("*#", *var->value))) {
1157                         mohclass->digit = *var->value;
1158                 } else if (!strcasecmp(var->name, "random")) {
1159                         static int deprecation_warning = 0;
1160                         if (!deprecation_warning) {
1161                                 ast_log(LOG_WARNING, "Music on hold 'random' setting is deprecated in 14.  Please use 'sort=random' instead.\n");
1162                                 deprecation_warning = 1;
1163                         }
1164                         ast_set2_flag(mohclass, ast_true(var->value), MOH_RANDOMIZE);
1165                 } else if (!strcasecmp(var->name, "sort")) {
1166                         if (!strcasecmp(var->value, "random")) {
1167                                 ast_set_flag(mohclass, MOH_RANDOMIZE);
1168                         } else if (!strcasecmp(var->value, "alpha")) {
1169                                 ast_set_flag(mohclass, MOH_SORTALPHA);
1170                         } else if (!strcasecmp(var->value, "randstart")) {
1171                                 ast_set_flag(mohclass, MOH_RANDSTART);
1172                         }
1173                 } else if (!strcasecmp(var->name, "format") && !ast_strlen_zero(var->value)) {
1174                         ao2_cleanup(mohclass->format);
1175                         mohclass->format = ast_format_cache_get(var->value);
1176                         if (!mohclass->format) {
1177                                 ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value);
1178                                 mohclass->format = ao2_bump(ast_format_slin);
1179                         }
1180                 } else if (!strcasecmp(var->name, "kill_escalation_delay")) {
1181                         if (sscanf(var->value, "%zu", &mohclass->kill_delay) == 1) {
1182                                 mohclass->kill_delay *= 1000;
1183                         } else {
1184                                 ast_log(LOG_WARNING, "kill_escalation_delay '%s' is invalid.  Setting to 100ms\n", var->value);
1185                                 mohclass->kill_delay = 100000;
1186                         }
1187                 } else if (!strcasecmp(var->name, "kill_method")) {
1188                         if (!strcasecmp(var->value, "process")) {
1189                                 mohclass->kill_method = KILL_METHOD_PROCESS;
1190                         } else if (!strcasecmp(var->value, "process_group")) {
1191                                 mohclass->kill_method = KILL_METHOD_PROCESS_GROUP;
1192                         } else {
1193                                 ast_log(LOG_WARNING, "kill_method '%s' is invalid.  Setting to 'process_group'\n", var->value);
1194                                 mohclass->kill_method = KILL_METHOD_PROCESS_GROUP;
1195                         }
1196                 }
1197         }
1198
1199         if (playlist_entries) {
1200                 /* If we aren't in playlist mode, drop any list we may have already built */
1201                 if (strcasecmp(mohclass->mode, "playlist")) {
1202                         ast_log(LOG_NOTICE, "Ignoring playlist entries because we are in '%s' mode.\n",
1203                                 mohclass->mode);
1204                         ao2_ref(playlist_entries, -1);
1205                         return;
1206                 }
1207
1208                 AST_VECTOR_COMPACT(playlist_entries);
1209
1210                 /* We don't need to lock here because we are the thread that
1211                  * created this mohclass and we haven't published it yet */
1212                 ao2_ref(mohclass->files, -1);
1213                 mohclass->files = playlist_entries;
1214         }
1215 }
1216
1217 static int on_moh_file(const char *directory, const char *filename, void *obj)
1218 {
1219         struct ast_vector_string *files = obj;
1220         char *full_path;
1221         char *extension;
1222
1223         /* Skip files that starts with a dot */
1224         if (*filename == '.') {
1225                 ast_debug(4, "Skipping '%s/%s' because it starts with a dot\n",
1226                         directory, filename);
1227                 return 0;
1228         }
1229
1230         /* We can't do anything with files that don't have an extension,
1231          * so check that first and punt if we can't find something */
1232         extension = strrchr(filename, '.');
1233         if (!extension) {
1234                 ast_debug(4, "Skipping '%s/%s' because it doesn't have an extension\n",
1235                         directory, filename);
1236                 return 0;
1237         }
1238
1239         /* The extension needs at least two characters (after the .) to be useful */
1240         if (strlen(extension) < 3) {
1241                 ast_debug(4, "Skipping '%s/%s' because it doesn't have at least a two "
1242                         "character extension\n", directory, filename);
1243                 return 0;
1244         }
1245
1246         /* Build the full path (excluding the extension) */
1247         if (ast_asprintf(&full_path, "%s/%.*s",
1248                         directory,
1249                         (int) (extension - filename), filename) < 0) {
1250                 /* If we don't have enough memory to build this path, there is no
1251                  * point in continuing */
1252                 return 1;
1253         }
1254
1255         /* If the file is present in multiple formats, ensure we only put it
1256          * into the list once. Pretty sure this is O(n^2). */
1257         if (AST_VECTOR_GET_CMP(files, &full_path[0], !strcmp)) {
1258                 ast_free(full_path);
1259                 return 0;
1260         }
1261
1262         if (AST_VECTOR_APPEND(files, full_path)) {
1263                 /* AST_VECTOR_APPEND() can only fail on allocation failure, so
1264                  * we stop iterating */
1265                 ast_free(full_path);
1266                 return 1;
1267         }
1268
1269         return 0;
1270 }
1271
1272 static int moh_filename_strcasecmp(const void *a, const void *b)
1273 {
1274         const char **s1 = (const char **) a;
1275         const char **s2 = (const char **) b;
1276         return strcasecmp(*s1, *s2);
1277 }
1278
1279 static int moh_scan_files(struct mohclass *class) {
1280
1281         char dir_path[PATH_MAX - sizeof(class->dir)];
1282         struct ast_vector_string *files;
1283
1284         if (class->dir[0] != '/') {
1285                 snprintf(dir_path, sizeof(dir_path), "%s/%s", ast_config_AST_DATA_DIR, class->dir);
1286         } else {
1287                 ast_copy_string(dir_path, class->dir, sizeof(dir_path));
1288         }
1289
1290         ast_debug(4, "Scanning '%s' for files for class '%s'\n", dir_path, class->name);
1291
1292         /* 16 seems like a reasonable default */
1293         files = moh_file_vector_alloc(16);
1294         if (!files) {
1295                 return -1;
1296         }
1297
1298         if (ast_file_read_dir(dir_path, on_moh_file, files)) {
1299                 ao2_ref(files, -1);
1300                 return -1;
1301         }
1302
1303         if (ast_test_flag(class, MOH_SORTALPHA)) {
1304                 AST_VECTOR_SORT(files, moh_filename_strcasecmp);
1305         }
1306
1307         AST_VECTOR_COMPACT(files);
1308
1309         ao2_lock(class);
1310         ao2_ref(class->files, -1);
1311         class->files = files;
1312         ao2_unlock(class);
1313
1314         return AST_VECTOR_SIZE(files);
1315 }
1316
1317 static int init_files_class(struct mohclass *class)
1318 {
1319         int res;
1320
1321         res = moh_scan_files(class);
1322
1323         if (res < 0) {
1324                 return -1;
1325         }
1326
1327         if (!res) {
1328                 ast_verb(3, "Files not found in %s for moh class:%s\n",
1329                         class->dir, class->name);
1330                 return -1;
1331         }
1332
1333         return 0;
1334 }
1335
1336 static void moh_rescan_files(void) {
1337         struct ao2_iterator i;
1338         struct mohclass *c;
1339
1340         i = ao2_iterator_init(mohclasses, 0);
1341
1342         while ((c = ao2_iterator_next(&i))) {
1343                 if (!strcasecmp(c->mode, "files")) {
1344                         moh_scan_files(c);
1345                 }
1346                 ao2_ref(c, -1);
1347         }
1348
1349         ao2_iterator_destroy(&i);
1350 }
1351
1352 static int moh_diff(struct mohclass *old, struct mohclass *new)
1353 {
1354         if (!old || !new) {
1355                 return -1;
1356         }
1357
1358         if (strcmp(old->dir, new->dir)) {
1359                 return -1;
1360         } else if (strcmp(old->mode, new->mode)) {
1361                 return -1;
1362         } else if (strcmp(old->args, new->args)) {
1363                 return -1;
1364         } else if (old->flags != new->flags) {
1365                 return -1;
1366         }
1367
1368         return 0;
1369 }
1370
1371 static int init_app_class(struct mohclass *class)
1372 {
1373         if (!strcasecmp(class->mode, "custom")) {
1374                 ast_set_flag(class, MOH_CUSTOM);
1375         } else if (!strcasecmp(class->mode, "mp3nb")) {
1376                 ast_set_flag(class, MOH_SINGLE);
1377         } else if (!strcasecmp(class->mode, "quietmp3nb")) {
1378                 ast_set_flag(class, MOH_SINGLE | MOH_QUIET);
1379         } else if (!strcasecmp(class->mode, "quietmp3")) {
1380                 ast_set_flag(class, MOH_QUIET);
1381         }
1382
1383         class->srcfd = -1;
1384
1385         if (!(class->timer = ast_timer_open())) {
1386                 ast_log(LOG_WARNING, "Unable to create timer: %s\n", strerror(errno));
1387                 return -1;
1388         }
1389         if (class->timer && ast_timer_set_rate(class->timer, 25)) {
1390                 ast_log(LOG_WARNING, "Unable to set 40ms frame rate: %s\n", strerror(errno));
1391                 ast_timer_close(class->timer);
1392                 class->timer = NULL;
1393         }
1394
1395         if (ast_pthread_create_background(&class->thread, NULL, monmp3thread, class)) {
1396                 ast_log(LOG_WARNING, "Unable to create moh thread...\n");
1397                 if (class->timer) {
1398                         ast_timer_close(class->timer);
1399                         class->timer = NULL;
1400                 }
1401                 return -1;
1402         }
1403
1404         return 0;
1405 }
1406
1407 /*!
1408  * \note This function owns the reference it gets to moh if unref is true
1409  */
1410 #define moh_register(moh, reload, unref) _moh_register(moh, reload, unref, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1411 static int _moh_register(struct mohclass *moh, int reload, int unref, const char *file, int line, const char *funcname)
1412 {
1413         struct mohclass *mohclass = NULL;
1414
1415         mohclass = _get_mohbyname(moh->name, 0, MOH_NOTDELETED, file, line, funcname);
1416
1417         if (mohclass && !moh_diff(mohclass, moh)) {
1418                 ast_log(LOG_WARNING, "Music on Hold class '%s' already exists\n", moh->name);
1419                 mohclass = mohclass_unref(mohclass, "unreffing mohclass we just found by name");
1420                 if (unref) {
1421                         moh = mohclass_unref(moh, "unreffing potential new moh class (it is a duplicate)");
1422                 }
1423                 return -1;
1424         } else if (mohclass) {
1425                 /* Found a class, but it's different from the one being registered */
1426                 mohclass = mohclass_unref(mohclass, "unreffing mohclass we just found by name");
1427         }
1428
1429         time(&moh->start);
1430         moh->start -= respawn_time;
1431
1432         if (!strcasecmp(moh->mode, "files")) {
1433                 if (init_files_class(moh)) {
1434                         if (unref) {
1435                                 moh = mohclass_unref(moh, "unreffing potential new moh class (init_files_class failed)");
1436                         }
1437                         return -1;
1438                 }
1439         } else if (!strcasecmp(moh->mode, "playlist")) {
1440                 size_t file_count;
1441
1442                 ao2_lock(moh);
1443                 file_count = AST_VECTOR_SIZE(moh->files);
1444                 ao2_unlock(moh);
1445
1446                 if (!file_count) {
1447                         if (unref) {
1448                                 moh = mohclass_unref(moh, "unreffing potential new moh class (no playlist entries)");
1449                         }
1450                         return -1;
1451                 }
1452         } else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") ||
1453                         !strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") ||
1454                         !strcasecmp(moh->mode, "httpmp3") || !strcasecmp(moh->mode, "custom")) {
1455                 if (init_app_class(moh)) {
1456                         if (unref) {
1457                                 moh = mohclass_unref(moh, "unreffing potential new moh class (init_app_class_failed)");
1458                         }
1459                         return -1;
1460                 }
1461         } else {
1462                 ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", moh->mode);
1463                 if (unref) {
1464                         moh = mohclass_unref(moh, "unreffing potential new moh class (unknown mode)");
1465                 }
1466                 return -1;
1467         }
1468
1469         ao2_t_link(mohclasses, moh, "Adding class to container");
1470
1471         if (unref) {
1472                 moh = mohclass_unref(moh, "Unreffing new moh class because we just added it to the container");
1473         }
1474
1475         return 0;
1476 }
1477
1478 #define moh_unregister(a) _moh_unregister(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1479 static int _moh_unregister(struct mohclass *moh, const char *file, int line, const char *funcname)
1480 {
1481         ao2_t_unlink(mohclasses, moh, "Removing class from container");
1482         return 0;
1483 }
1484
1485 static void local_ast_moh_cleanup(struct ast_channel *chan)
1486 {
1487         struct moh_files_state *state = ast_channel_music_state(chan);
1488
1489         if (state) {
1490                 ast_channel_music_state_set(chan, NULL);
1491                 if (state->class) {
1492                         /* This should never happen.  We likely just leaked some resource. */
1493                         state->class =
1494                                 mohclass_unref(state->class, "Uh Oh. Cleaning up MOH with an active class");
1495                         ast_log(LOG_WARNING, "Uh Oh. Cleaning up MOH with an active class\n");
1496                 }
1497                 ao2_cleanup(state->origwfmt);
1498                 ao2_cleanup(state->mohwfmt);
1499                 ast_free(state);
1500                 /* Only held a module reference if we had a music state */
1501                 ast_module_unref(ast_module_info->self);
1502         }
1503 }
1504
1505 /*! \brief Support routing for 'moh unregister class' CLI
1506  * This is in charge of generating all strings that match a prefix in the
1507  * given position. As many functions of this kind, each invokation has
1508  * O(state) time complexity so be careful in using it.
1509  */
1510 static char *complete_mohclass_realtime(const char *line, const char *word, int pos, int state)
1511 {
1512         int which=0;
1513         struct mohclass *cur;
1514         char *c = NULL;
1515         int wordlen = strlen(word);
1516         struct ao2_iterator i;
1517
1518         if (pos != 3) {
1519                 return NULL;
1520         }
1521
1522         i = ao2_iterator_init(mohclasses, 0);
1523         while ((cur = ao2_t_iterator_next(&i, "iterate thru mohclasses"))) {
1524                 if (cur->realtime && !strncasecmp(cur->name, word, wordlen) && ++which > state) {
1525                         c = ast_strdup(cur->name);
1526                         mohclass_unref(cur, "drop ref in iterator loop break");
1527                         break;
1528                 }
1529                 mohclass_unref(cur, "drop ref in iterator loop");
1530         }
1531         ao2_iterator_destroy(&i);
1532
1533         return c;
1534 }
1535
1536 static char *handle_cli_moh_unregister_class(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1537 {
1538         struct mohclass *cur;
1539         int len;
1540         int found = 0;
1541         struct ao2_iterator i;
1542
1543         switch (cmd) {
1544                 case CLI_INIT:
1545                         e->command = "moh unregister class";
1546                         e->usage =
1547                                 "Usage: moh unregister class <class>\n"
1548                                 "       Unregisters a realtime moh class.\n";
1549                         return NULL;
1550                 case CLI_GENERATE:
1551                         return complete_mohclass_realtime(a->line, a->word, a->pos, a->n);
1552         }
1553
1554         if (a->argc != 4)
1555                 return CLI_SHOWUSAGE;
1556
1557         len = strlen(a->argv[3]);
1558
1559         i = ao2_iterator_init(mohclasses, 0);
1560         while ((cur = ao2_t_iterator_next(&i, "iterate thru mohclasses"))) {
1561                 if (cur->realtime && len == strlen(cur->name) && !strncasecmp(cur->name, a->argv[3], len)) {
1562                         found = 1;
1563                         break;
1564                 }
1565                 mohclass_unref(cur, "drop ref in iterator loop");
1566         }
1567         ao2_iterator_destroy(&i);
1568
1569         if (found) {
1570                 moh_unregister(cur);
1571                 mohclass_unref(cur, "drop ref after unregister");
1572         } else {
1573                 ast_cli(a->fd, "No such realtime moh class '%s'\n", a->argv[3]);
1574         }
1575
1576         return CLI_SUCCESS;
1577 }
1578
1579
1580
1581 static void moh_class_destructor(void *obj);
1582
1583 #define moh_class_malloc()      _moh_class_malloc(__FILE__,__LINE__,__PRETTY_FUNCTION__)
1584
1585 static struct mohclass *_moh_class_malloc(const char *file, int line, const char *funcname)
1586 {
1587         struct mohclass *class;
1588
1589         class = __ao2_alloc(sizeof(*class), moh_class_destructor, AO2_ALLOC_OPT_LOCK_MUTEX,
1590                 "Allocating new moh class", file, line, funcname);
1591         if (class) {
1592                 class->format = ao2_bump(ast_format_slin);
1593                 class->srcfd = -1;
1594                 class->kill_delay = 100000;
1595
1596                 /* We create an empty one by default */
1597                 class->files = moh_file_vector_alloc(0);
1598                 if (!class->files) {
1599                         ao2_ref(class, -1);
1600                         return NULL;
1601                 }
1602         }
1603
1604         return class;
1605 }
1606
1607 static struct ast_variable *load_realtime_musiconhold(const char *name)
1608 {
1609         struct ast_variable *var = ast_load_realtime("musiconhold", "name", name, SENTINEL);
1610
1611         if (var) {
1612                 const char *mode = ast_variable_find_in_list(var, "mode");
1613                 if (ast_strings_equal(mode, "playlist")) {
1614                         struct ast_config *entries = ast_load_realtime_multientry("musiconhold_entry", "position >=", "0", "name", name, SENTINEL);
1615                         char *category = NULL;
1616                         size_t entry_count = 0;
1617
1618                         /* entries is NULL if there are no results */
1619                         if (entries) {
1620                                 while ((category = ast_category_browse(entries, category))) {
1621                                         const char *entry = ast_variable_retrieve(entries, category, "entry");
1622
1623                                         if (entry) {
1624                                                 struct ast_variable *dup = ast_variable_new("entry", entry, "");
1625                                                 if (dup) {
1626                                                         entry_count++;
1627                                                         ast_variable_list_append(&var, dup);
1628                                                 }
1629                                         }
1630                                 }
1631                                 ast_config_destroy(entries);
1632                         }
1633
1634                         if (entry_count == 0) {
1635                                 /* Behave as though this class doesn't exist */
1636                                 ast_variables_destroy(var);
1637                                 var = NULL;
1638                         }
1639                 }
1640         }
1641
1642         if (!var) {
1643                 ast_log(LOG_WARNING,
1644                         "Music on Hold class '%s' not found in memory/database. "
1645                         "Verify your configuration.\n",
1646                         name);
1647         }
1648         return var;
1649 }
1650
1651 static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
1652 {
1653         struct mohclass *mohclass = NULL;
1654         struct moh_files_state *state = ast_channel_music_state(chan);
1655         struct ast_variable *var = NULL;
1656         int res = 0;
1657         int i;
1658         int realtime_possible = ast_check_realtime("musiconhold");
1659         int warn_if_not_in_memory = !realtime_possible;
1660         const char *classes[] = {NULL, NULL, interpclass, "default"};
1661
1662         if (ast_test_flag(global_flags, MOH_PREFERCHANNELCLASS)) {
1663                 classes[0] = ast_channel_musicclass(chan);
1664                 classes[1] = mclass;
1665         } else {
1666                 classes[0] = mclass;
1667                 classes[1] = ast_channel_musicclass(chan);
1668         }
1669
1670         /* The following is the order of preference for which class to use:
1671          * 1) The channels explicitly set musicclass, which should *only* be
1672          *    set by a call to Set(CHANNEL(musicclass)=whatever) in the dialplan.
1673          *    Unless preferchannelclass in musiconhold.conf is false
1674          * 2) The mclass argument. If a channel is calling ast_moh_start() as the
1675          *    result of receiving a HOLD control frame, this should be the
1676          *    payload that came with the frame.
1677          * 3) The channels explicitly set musicclass, which should *only* be
1678          *    set by a call to Set(CHANNEL(musicclass)=whatever) in the dialplan.
1679          * 4) The interpclass argument. This would be from the mohinterpret
1680          *    option from channel drivers. This is the same as the old musicclass
1681          *    option.
1682          * 5) The default class.
1683          */
1684
1685         for (i = 0; i < ARRAY_LEN(classes); ++i) {
1686                 if (!ast_strlen_zero(classes[i])) {
1687                         mohclass = get_mohbyname(classes[i], warn_if_not_in_memory, 0);
1688                         if (!mohclass && realtime_possible) {
1689                                 var = load_realtime_musiconhold(classes[i]);
1690                         }
1691                         if (mohclass || var) {
1692                                 break;
1693                         }
1694                 }
1695         }
1696
1697         /* If no moh class found in memory, then check RT. Note that the logic used
1698          * above guarantees that if var is non-NULL, then mohclass must be NULL.
1699          */
1700         if (var) {
1701                 if ((mohclass = moh_class_malloc())) {
1702                         mohclass->realtime = 1;
1703
1704                         moh_parse_options(var, mohclass);
1705                         ast_variables_destroy(var);
1706
1707                         if (ast_strlen_zero(mohclass->dir)) {
1708                                 if (!strcasecmp(mohclass->mode, "custom") || !strcasecmp(mohclass->mode, "playlist")) {
1709                                         strcpy(mohclass->dir, "nodir");
1710                                 } else {
1711                                         ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", mohclass->name);
1712                                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no directory specified)");
1713                                         return -1;
1714                                 }
1715                         }
1716                         if (ast_strlen_zero(mohclass->mode)) {
1717                                 ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", mohclass->name);
1718                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no mode specified)");
1719                                 return -1;
1720                         }
1721                         if (ast_strlen_zero(mohclass->args) && !strcasecmp(mohclass->mode, "custom")) {
1722                                 ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", mohclass->name);
1723                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no app specified for custom mode");
1724                                 return -1;
1725                         }
1726
1727                         if (ast_test_flag(global_flags, MOH_CACHERTCLASSES)) {
1728                                 /* CACHERTCLASSES enabled, let's add this class to default tree */
1729                                 if (state && state->class) {
1730                                         /* Class already exist for this channel */
1731                                         ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name);
1732                                 }
1733                                 /* We don't want moh_register to unref the mohclass because we do it at the end of this function as well.
1734                                  * If we allowed moh_register to unref the mohclass,too, then the count would be off by one. The result would
1735                                  * be that the destructor would be called when the generator on the channel is deactivated. The container then
1736                                  * has a pointer to a freed mohclass, so any operations involving the mohclass container would result in reading
1737                                  * invalid memory.
1738                                  */
1739                                 if (moh_register(mohclass, 0, DONT_UNREF) == -1) {
1740                                         mohclass = mohclass_unref(mohclass, "unreffing mohclass failed to register");
1741                                         return -1;
1742                                 }
1743                         } else {
1744                                 /* We don't register RT moh class, so let's init it manualy */
1745
1746                                 time(&mohclass->start);
1747                                 mohclass->start -= respawn_time;
1748
1749                                 if (!strcasecmp(mohclass->mode, "files")) {
1750                                         /*
1751                                          * XXX moh_scan_files returns -1 if it is unable to open the
1752                                          * configured directory or there is a memory allocation
1753                                          * failure. Otherwise it returns the number of files for this music
1754                                          * class. This check is only checking if the number of files is zero
1755                                          * and it ignores the -1 case. To avoid a behavior change we keep this
1756                                          * as-is, but we should address what the 'correct' behavior should be.
1757                                          */
1758                                         if (!moh_scan_files(mohclass)) {
1759                                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (moh_scan_files failed)");
1760                                                 return -1;
1761                                         }
1762                                         if (strchr(mohclass->args, 'r')) {
1763                                                 static int deprecation_warning = 0;
1764                                                 if (!deprecation_warning) {
1765                                                         ast_log(LOG_WARNING, "Music on hold 'application=r' setting is deprecated in 14.  Please use 'sort=random' instead.\n");
1766                                                         deprecation_warning = 1;
1767                                                 }
1768                                                 ast_set_flag(mohclass, MOH_RANDOMIZE);
1769                                         }
1770                                 } else if (!strcasecmp(mohclass->mode, "playlist")) {
1771                                         size_t file_count;
1772
1773                                         ao2_lock(mohclass);
1774                                         file_count = AST_VECTOR_SIZE(mohclass->files);
1775                                         ao2_unlock(mohclass);
1776
1777                                         if (!file_count) {
1778                                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no playlist entries)");
1779                                                 return -1;
1780                                         }
1781                                 } else if (!strcasecmp(mohclass->mode, "mp3") || !strcasecmp(mohclass->mode, "mp3nb") || !strcasecmp(mohclass->mode, "quietmp3") || !strcasecmp(mohclass->mode, "quietmp3nb") || !strcasecmp(mohclass->mode, "httpmp3") || !strcasecmp(mohclass->mode, "custom")) {
1782
1783                                         if (!strcasecmp(mohclass->mode, "custom"))
1784                                                 ast_set_flag(mohclass, MOH_CUSTOM);
1785                                         else if (!strcasecmp(mohclass->mode, "mp3nb"))
1786                                                 ast_set_flag(mohclass, MOH_SINGLE);
1787                                         else if (!strcasecmp(mohclass->mode, "quietmp3nb"))
1788                                                 ast_set_flag(mohclass, MOH_SINGLE | MOH_QUIET);
1789                                         else if (!strcasecmp(mohclass->mode, "quietmp3"))
1790                                                 ast_set_flag(mohclass, MOH_QUIET);
1791
1792                                         mohclass->srcfd = -1;
1793                                         if (!(mohclass->timer = ast_timer_open())) {
1794                                                 ast_log(LOG_WARNING, "Unable to create timer: %s\n", strerror(errno));
1795                                         }
1796                                         if (mohclass->timer && ast_timer_set_rate(mohclass->timer, 25)) {
1797                                                 ast_log(LOG_WARNING, "Unable to set 40ms frame rate: %s\n", strerror(errno));
1798                                                 ast_timer_close(mohclass->timer);
1799                                                 mohclass->timer = NULL;
1800                                         }
1801
1802                                         /* Let's check if this channel already had a moh class before */
1803                                         if (state && state->class) {
1804                                                 /* Class already exist for this channel */
1805                                                 ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name);
1806                                                 if (state->class->realtime && !ast_test_flag(global_flags, MOH_CACHERTCLASSES) && !strcasecmp(mohclass->name, state->class->name)) {
1807                                                         /* we found RT class with the same name, seems like we should continue playing existing one */
1808                                                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (channel already has one)");
1809                                                         mohclass = mohclass_ref(state->class, "using existing class from state");
1810                                                 }
1811                                         } else {
1812                                                 if (ast_pthread_create_background(&mohclass->thread, NULL, monmp3thread, mohclass)) {
1813                                                         ast_log(LOG_WARNING, "Unable to create moh...\n");
1814                                                         if (mohclass->timer) {
1815                                                                 ast_timer_close(mohclass->timer);
1816                                                                 mohclass->timer = NULL;
1817                                                         }
1818                                                         mohclass = mohclass_unref(mohclass, "Unreffing potential mohclass (failed to create background thread)");
1819                                                         return -1;
1820                                                 }
1821                                         }
1822                                 } else {
1823                                         ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mohclass->mode);
1824                                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (unknown mode)");
1825                                         return -1;
1826                                 }
1827                         }
1828                 } else {
1829                         ast_variables_destroy(var);
1830                         var = NULL;
1831                 }
1832         }
1833
1834         if (!mohclass) {
1835                 return -1;
1836         }
1837
1838         /* If we are using a cached realtime class with files, re-scan the files */
1839         if (!var && ast_test_flag(global_flags, MOH_CACHERTCLASSES) && mohclass->realtime && !strcasecmp(mohclass->mode, "files")) {
1840                 /*
1841                  * XXX moh_scan_files returns -1 if it is unable to open the configured directory
1842                  * or there is a memory allocation failure. Otherwise it returns the number of
1843                  * files for this music class. This check is only checking if the number of files
1844                  * is zero and it ignores the -1 case. To avoid a behavior change we keep this
1845                  * as-is, but we should address what the 'correct' behavior should be.
1846                  */
1847                 if (!moh_scan_files(mohclass)) {
1848                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (moh_scan_files failed)");
1849                         return -1;
1850                 }
1851         }
1852
1853         if (!state || !state->class || strcmp(mohclass->name, state->class->name)) {
1854                 size_t file_count;
1855
1856                 ao2_lock(mohclass);
1857                 file_count = AST_VECTOR_SIZE(mohclass->files);
1858                 ao2_unlock(mohclass);
1859
1860                 if (file_count) {
1861                         res = ast_activate_generator(chan, &moh_file_stream, mohclass);
1862                 } else {
1863                         res = ast_activate_generator(chan, &mohgen, mohclass);
1864                 }
1865         }
1866         if (!res) {
1867                 ast_channel_lock(chan);
1868                 ast_channel_latest_musicclass_set(chan, mohclass->name);
1869                 ast_set_flag(ast_channel_flags(chan), AST_FLAG_MOH);
1870                 ast_channel_unlock(chan);
1871         }
1872
1873         mohclass = mohclass_unref(mohclass, "unreffing local reference to mohclass in local_ast_moh_start");
1874
1875         return res;
1876 }
1877
1878 static void local_ast_moh_stop(struct ast_channel *chan)
1879 {
1880         ast_deactivate_generator(chan);
1881
1882         ast_channel_lock(chan);
1883         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_MOH);
1884         if (ast_channel_music_state(chan)) {
1885                 if (ast_channel_stream(chan)) {
1886                         ast_closestream(ast_channel_stream(chan));
1887                         ast_channel_stream_set(chan, NULL);
1888                 }
1889         }
1890         ast_channel_unlock(chan);
1891 }
1892
1893 static void moh_class_destructor(void *obj)
1894 {
1895         struct mohclass *class = obj;
1896         struct mohdata *member;
1897         pthread_t tid = 0;
1898
1899         ast_debug(1, "Destroying MOH class '%s'\n", class->name);
1900
1901         ao2_lock(class);
1902         while ((member = AST_LIST_REMOVE_HEAD(&class->members, list))) {
1903                 ast_free(member);
1904         }
1905         ao2_cleanup(class->files);
1906         ao2_unlock(class);
1907
1908         /* Kill the thread first, so it cannot restart the child process while the
1909          * class is being destroyed */
1910         if (class->thread != AST_PTHREADT_NULL && class->thread != 0) {
1911                 tid = class->thread;
1912                 class->thread = AST_PTHREADT_NULL;
1913                 pthread_cancel(tid);
1914                 /* We'll collect the exit status later, after we ensure all the readers
1915                  * are dead. */
1916         }
1917
1918         if (class->pid > 1) {
1919                 char buff[8192];
1920                 int bytes, tbytes = 0, stime = 0;
1921
1922                 ast_debug(1, "killing %d!\n", class->pid);
1923
1924                 stime = time(NULL) + 2;
1925                 killpid(class->pid, class->kill_delay, class->kill_method);
1926
1927                 while ((ast_wait_for_input(class->srcfd, 100) > 0) &&
1928                                 (bytes = read(class->srcfd, buff, 8192)) && time(NULL) < stime) {
1929                         tbytes = tbytes + bytes;
1930                 }
1931
1932                 ast_debug(1, "mpg123 pid %d and child died after %d bytes read\n",
1933                         class->pid, tbytes);
1934
1935                 class->pid = 0;
1936                 close(class->srcfd);
1937                 class->srcfd = -1;
1938         }
1939
1940         if (class->timer) {
1941                 ast_timer_close(class->timer);
1942                 class->timer = NULL;
1943         }
1944
1945         ao2_cleanup(class->format);
1946
1947         /* Finally, collect the exit status of the monitor thread */
1948         if (tid > 0) {
1949                 pthread_join(tid, NULL);
1950         }
1951
1952 }
1953
1954 static int moh_class_mark(void *obj, void *arg, int flags)
1955 {
1956         struct mohclass *class = obj;
1957
1958         if ( ((flags & MOH_REALTIME) && class->realtime) || !(flags & MOH_REALTIME) ) {
1959                 class->delete = 1;
1960         }
1961
1962         return 0;
1963 }
1964
1965 static int moh_classes_delete_marked(void *obj, void *arg, int flags)
1966 {
1967         struct mohclass *class = obj;
1968
1969         return class->delete ? CMP_MATCH : 0;
1970 }
1971
1972 static int load_moh_classes(int reload)
1973 {
1974         struct ast_config *cfg;
1975         struct ast_variable *var;
1976         struct mohclass *class;
1977         char *cat;
1978         int numclasses = 0;
1979         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1980
1981         cfg = ast_config_load("musiconhold.conf", config_flags);
1982
1983         if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
1984                 if (ast_check_realtime("musiconhold") && reload) {
1985                         ao2_t_callback(mohclasses, OBJ_NODATA | MOH_REALTIME, moh_class_mark, NULL, "Mark realtime classes for deletion");
1986                         ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, moh_classes_delete_marked, NULL, "Purge marked classes");
1987                 }
1988                 moh_rescan_files();
1989                 return 0;
1990         }
1991
1992         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
1993                 if (ast_check_realtime("musiconhold") && reload) {
1994                         ao2_t_callback(mohclasses, OBJ_NODATA, moh_class_mark, NULL, "Mark deleted classes");
1995                         ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, moh_classes_delete_marked, NULL, "Purge marked classes");
1996                 }
1997                 return 0;
1998         }
1999
2000         if (reload) {
2001                 ao2_t_callback(mohclasses, OBJ_NODATA, moh_class_mark, NULL, "Mark deleted classes");
2002         }
2003
2004         ast_clear_flag(global_flags, AST_FLAGS_ALL);
2005         ast_set2_flag(global_flags, 1, MOH_PREFERCHANNELCLASS);
2006
2007         cat = ast_category_browse(cfg, NULL);
2008         for (; cat; cat = ast_category_browse(cfg, cat)) {
2009                 /* Setup common options from [general] section */
2010                 if (!strcasecmp(cat, "general")) {
2011                         for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
2012                                 if (!strcasecmp(var->name, "cachertclasses")) {
2013                                         ast_set2_flag(global_flags, ast_true(var->value), MOH_CACHERTCLASSES);
2014                                 } else if (!strcasecmp(var->name, "preferchannelclass")) {
2015                                         ast_set2_flag(global_flags, ast_true(var->value), MOH_PREFERCHANNELCLASS);
2016                                 } else {
2017                                         ast_log(LOG_WARNING, "Unknown option '%s' in [general] section of musiconhold.conf\n", var->name);
2018                                 }
2019                         }
2020                         continue;
2021                 }
2022
2023                 if (!(class = moh_class_malloc())) {
2024                         break;
2025                 }
2026
2027                 moh_parse_options(ast_variable_browse(cfg, cat), class);
2028                 /* For compatibility with the past, we overwrite any name=name
2029                  * with the context [name]. */
2030                 ast_copy_string(class->name, cat, sizeof(class->name));
2031
2032                 if (ast_strlen_zero(class->dir)) {
2033                         if (!strcasecmp(class->mode, "custom") || !strcasecmp(class->mode, "playlist")) {
2034                                 strcpy(class->dir, "nodir");
2035                         } else {
2036                                 ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", class->name);
2037                                 class = mohclass_unref(class, "unreffing potential mohclass (no directory)");
2038                                 continue;
2039                         }
2040                 }
2041                 if (ast_strlen_zero(class->mode)) {
2042                         ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", class->name);
2043                         class = mohclass_unref(class, "unreffing potential mohclass (no mode)");
2044                         continue;
2045                 }
2046                 if (ast_strlen_zero(class->args) && !strcasecmp(class->mode, "custom")) {
2047                         ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", class->name);
2048                         class = mohclass_unref(class, "unreffing potential mohclass (no app for custom mode)");
2049                         continue;
2050                 }
2051
2052                 /* Don't leak a class when it's already registered */
2053                 if (!moh_register(class, reload, HANDLE_REF)) {
2054                         numclasses++;
2055                 }
2056         }
2057
2058         ast_config_destroy(cfg);
2059
2060         ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE,
2061                         moh_classes_delete_marked, NULL, "Purge marked classes");
2062
2063         return numclasses;
2064 }
2065
2066 static void ast_moh_destroy(void)
2067 {
2068         ast_verb(2, "Destroying musiconhold processes\n");
2069         if (mohclasses) {
2070                 ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "Destroy callback");
2071                 ao2_ref(mohclasses, -1);
2072                 mohclasses = NULL;
2073         }
2074 }
2075
2076 static char *handle_cli_moh_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2077 {
2078         switch (cmd) {
2079         case CLI_INIT:
2080                 e->command = "moh reload";
2081                 e->usage =
2082                         "Usage: moh reload\n"
2083                         "       Reloads the MusicOnHold module.\n"
2084                         "       Alias for 'module reload res_musiconhold.so'\n";
2085                 return NULL;
2086         case CLI_GENERATE:
2087                 return NULL;
2088         }
2089
2090         if (a->argc != e->args)
2091                 return CLI_SHOWUSAGE;
2092
2093         /* The module loader will prevent concurrent reloads from occurring, so we delegate */
2094         ast_module_reload("res_musiconhold");
2095
2096         return CLI_SUCCESS;
2097 }
2098
2099 static char *handle_cli_moh_show_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2100 {
2101         struct mohclass *class;
2102         struct ao2_iterator i;
2103
2104         switch (cmd) {
2105         case CLI_INIT:
2106                 e->command = "moh show files";
2107                 e->usage =
2108                         "Usage: moh show files\n"
2109                         "       Lists all loaded file-based MusicOnHold classes and their\n"
2110                         "       files.\n";
2111                 return NULL;
2112         case CLI_GENERATE:
2113                 return NULL;
2114         }
2115
2116         if (a->argc != e->args)
2117                 return CLI_SHOWUSAGE;
2118
2119         i = ao2_iterator_init(mohclasses, 0);
2120         for (; (class = ao2_t_iterator_next(&i, "Show files iterator")); mohclass_unref(class, "Unref iterator in moh show files")) {
2121                 struct ast_vector_string *files;
2122
2123                 ao2_lock(class);
2124                 files = ao2_bump(class->files);
2125                 ao2_unlock(class);
2126
2127                 if (AST_VECTOR_SIZE(files)) {
2128                         int x;
2129                         ast_cli(a->fd, "Class: %s\n", class->name);
2130                         for (x = 0; x < AST_VECTOR_SIZE(files); x++) {
2131                                 ast_cli(a->fd, "\tFile: %s\n", AST_VECTOR_GET(files, x));
2132                         }
2133                 }
2134
2135                 ao2_ref(files, -1);
2136         }
2137         ao2_iterator_destroy(&i);
2138
2139         return CLI_SUCCESS;
2140 }
2141
2142 static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2143 {
2144         struct mohclass *class;
2145         struct ao2_iterator i;
2146
2147         switch (cmd) {
2148         case CLI_INIT:
2149                 e->command = "moh show classes";
2150                 e->usage =
2151                         "Usage: moh show classes\n"
2152                         "       Lists all MusicOnHold classes.\n";
2153                 return NULL;
2154         case CLI_GENERATE:
2155                 return NULL;
2156         }
2157
2158         if (a->argc != e->args)
2159                 return CLI_SHOWUSAGE;
2160
2161         i = ao2_iterator_init(mohclasses, 0);
2162         for (; (class = ao2_t_iterator_next(&i, "Show classes iterator")); mohclass_unref(class, "Unref iterator in moh show classes")) {
2163                 ast_cli(a->fd, "Class: %s\n", class->name);
2164                 ast_cli(a->fd, "\tMode: %s\n", S_OR(class->mode, "<none>"));
2165                 ast_cli(a->fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>"));
2166                 if (ast_test_flag(class, MOH_ANNOUNCEMENT)) {
2167                         ast_cli(a->fd, "\tAnnouncement: %s\n", S_OR(class->announcement, "<none>"));
2168                 }
2169                 if (ast_test_flag(class, MOH_CUSTOM)) {
2170                         ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
2171                         ast_cli(a->fd, "\tKill Escalation Delay: %zu ms\n", class->kill_delay / 1000);
2172                         ast_cli(a->fd, "\tKill Method: %s\n",
2173                                 class->kill_method == KILL_METHOD_PROCESS ? "process" : "process_group");
2174                 }
2175                 if (strcasecmp(class->mode, "files")) {
2176                         ast_cli(a->fd, "\tFormat: %s\n", ast_format_get_name(class->format));
2177                 }
2178         }
2179         ao2_iterator_destroy(&i);
2180
2181         return CLI_SUCCESS;
2182 }
2183
2184 static struct ast_cli_entry cli_moh[] = {
2185         AST_CLI_DEFINE(handle_cli_moh_reload,           "Reload MusicOnHold"),
2186         AST_CLI_DEFINE(handle_cli_moh_show_classes,     "List MusicOnHold classes"),
2187         AST_CLI_DEFINE(handle_cli_moh_show_files,       "List MusicOnHold file-based classes"),
2188         AST_CLI_DEFINE(handle_cli_moh_unregister_class, "Unregister realtime MusicOnHold class")
2189 };
2190
2191 static int moh_class_hash(const void *obj, const int flags)
2192 {
2193         const struct mohclass *class = obj;
2194
2195         return ast_str_case_hash(class->name);
2196 }
2197
2198 static int moh_class_cmp(void *obj, void *arg, int flags)
2199 {
2200         struct mohclass *class = obj, *class2 = arg;
2201
2202         return strcasecmp(class->name, class2->name) ? 0 :
2203                 (flags & MOH_NOTDELETED) && (class->delete || class2->delete) ? 0 :
2204                 CMP_MATCH | CMP_STOP;
2205 }
2206
2207 /*!
2208  * \brief Load the module
2209  *
2210  * Module loading including tests for configuration or dependencies.
2211  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
2212  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
2213  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
2214  * configuration file or other non-critical problem return
2215  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
2216  */
2217 static int load_module(void)
2218 {
2219         int res;
2220
2221         mohclasses = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, 53,
2222                 moh_class_hash, NULL, moh_class_cmp, "Moh class container");
2223         if (!mohclasses) {
2224                 return AST_MODULE_LOAD_DECLINE;
2225         }
2226
2227         if (!load_moh_classes(0) && ast_check_realtime("musiconhold") == 0) {   /* No music classes configured, so skip it */
2228                 ast_log(LOG_WARNING, "No music on hold classes configured, "
2229                                 "disabling music on hold.\n");
2230         } else {
2231                 ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop,
2232                                 local_ast_moh_cleanup);
2233         }
2234
2235         res = ast_register_application_xml(play_moh, play_moh_exec);
2236         ast_register_atexit(ast_moh_destroy);
2237         ast_cli_register_multiple(cli_moh, ARRAY_LEN(cli_moh));
2238         if (!res)
2239                 res = ast_register_application_xml(start_moh, start_moh_exec);
2240         if (!res)
2241                 res = ast_register_application_xml(stop_moh, stop_moh_exec);
2242
2243         return AST_MODULE_LOAD_SUCCESS;
2244 }
2245
2246 static int reload(void)
2247 {
2248         if (load_moh_classes(1)) {
2249                 ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop,
2250                                 local_ast_moh_cleanup);
2251         }
2252
2253         return AST_MODULE_LOAD_SUCCESS;
2254 }
2255
2256 static int moh_class_inuse(void *obj, void *arg, int flags)
2257 {
2258         struct mohclass *class = obj;
2259
2260         return AST_LIST_EMPTY(&class->members) ? 0 : CMP_MATCH | CMP_STOP;
2261 }
2262
2263 static int unload_module(void)
2264 {
2265         int res = 0;
2266         struct mohclass *class = NULL;
2267
2268         /* XXX This check shouldn't be required if module ref counting was being used
2269          * properly ... */
2270         if ((class = ao2_t_callback(mohclasses, 0, moh_class_inuse, NULL, "Module unload callback"))) {
2271                 class = mohclass_unref(class, "unref of class from module unload callback");
2272                 res = -1;
2273         }
2274
2275         if (res < 0) {
2276                 ast_log(LOG_WARNING, "Unable to unload res_musiconhold due to active MOH channels\n");
2277                 return res;
2278         }
2279
2280         ast_uninstall_music_functions();
2281
2282         ast_moh_destroy();
2283         res = ast_unregister_application(play_moh);
2284         res |= ast_unregister_application(start_moh);
2285         res |= ast_unregister_application(stop_moh);
2286         ast_cli_unregister_multiple(cli_moh, ARRAY_LEN(cli_moh));
2287         ast_unregister_atexit(ast_moh_destroy);
2288
2289         return res;
2290 }
2291
2292 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Music On Hold Resource",
2293         .support_level = AST_MODULE_SUPPORT_CORE,
2294         .load = load_module,
2295         .unload = unload_module,
2296         .reload = reload,
2297         .load_pri = AST_MODPRI_CHANNEL_DEPEND,
2298 );