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