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