Merge remaining audit patch (save dlfcn.c)
[asterisk/asterisk.git] / res / res_musiconhold.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Routines implementing music on hold
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/options.h>
20 #include <asterisk/module.h>
21 #include <asterisk/translate.h>
22 #include <asterisk/say.h>
23 #include <asterisk/channel_pvt.h>
24 #include <asterisk/musiconhold.h>
25 #include <asterisk/config.h>
26 #include <asterisk/utils.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <signal.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <sys/time.h>
35 #include <sys/signal.h>
36 #include <netinet/in.h>
37 #include <sys/stat.h>
38 #include <dirent.h>
39 #ifdef ZAPATA_MOH
40 #ifdef __linux__
41 #include <linux/zaptel.h>
42 #else
43 #include <zaptel.h>
44 #endif /* __linux__ */
45 #endif
46 #include <unistd.h>
47 #include <sys/ioctl.h>
48
49 static char *app0 = "MusicOnHold";
50 static char *app1 = "WaitMusicOnHold";
51 static char *app2 = "SetMusicOnHold";
52
53 static char *synopsis0 = "Play Music On Hold indefinitely";
54 static char *synopsis1 = "Wait, playing Music On Hold";
55 static char *synopsis2 = "Set default Music On Hold class";
56
57 static char *descrip0 = "MusicOnHold(class): "
58 "Plays hold music specified by class.  If omitted, the default\n"
59 "music source for the channel will be used. Set the default \n"
60 "class with the SetMusicOnHold() application.\n"
61 "Returns -1 on hangup.\n"
62 "Never returns otherwise.\n";
63
64 static char *descrip1 = "WaitMusicOnHold(delay): "
65 "Plays hold music specified number of seconds.  Returns 0 when\n"
66 "done, or -1 on hangup.  If no hold music is available, the delay will\n"
67 "still occur with no sound.\n";
68
69 static char *descrip2 = "SetMusicOnHold(class): "
70 "Sets the default class for music on hold for a given channel.  When\n"
71 "music on hold is activated, this class will be used to select which\n"
72 "music is played.\n";
73
74 struct mohclass {
75         char class[80];
76         char dir[256];
77         char miscargs[256];
78         int destroyme;
79         int pid;                /* PID of mpg123 */
80         int quiet;
81         int single;
82         pthread_t thread;
83         struct mohdata *members;
84         /* Source of audio */
85         int srcfd;
86         /* FD for timing source */
87         int pseudofd;
88         struct mohclass *next;
89 };
90
91 struct mohdata {
92         int pipe[2];
93         int origwfmt;
94         struct mohclass *parent;
95         struct mohdata *next;
96 };
97
98 static struct mohclass *mohclasses;
99
100 AST_MUTEX_DEFINE_STATIC(moh_lock);
101
102 #define LOCAL_MPG_123 "/usr/local/bin/mpg123"
103 #define MPG_123 "/usr/bin/mpg123"
104 #define MAX_MP3S 256
105
106 static int spawn_mp3(struct mohclass *class)
107 {
108         int fds[2];
109         int files;
110         char fns[MAX_MP3S][80];
111         char *argv[MAX_MP3S + 50];
112         char xargs[256];
113         char *argptr;
114         int argc = 0;
115         DIR *dir;
116         struct dirent *de;
117         dir = opendir(class->dir);
118         if (!dir) {
119                 ast_log(LOG_WARNING, "%s is not a valid directory\n", class->dir);
120                 return -1;
121         }
122         argv[argc++] = "mpg123";
123         argv[argc++] = "-q";
124         argv[argc++] = "-s";
125         argv[argc++] = "--mono";
126         argv[argc++] = "-r";
127         argv[argc++] = "8000";
128
129         if (!class->single) {
130                 argv[argc++] = "-b";
131                 argv[argc++] = "2048";
132         }
133
134         argv[argc++] = "-f";
135         
136         if (class->quiet) {
137                 argv[argc++] = "4096";
138         } else
139                 argv[argc++] = "8192";
140
141         /* Look for extra arguments and add them to the list */
142         strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
143         argptr = xargs;
144         while(argptr && !ast_strlen_zero(argptr)) {
145                 argv[argc++] = argptr;
146                 argptr = strchr(argptr, ',');
147                 if (argptr) {
148                         *argptr = '\0';
149                         argptr++;
150                 }
151         }
152
153         files = 0;
154         while((de = readdir(dir)) && (files < MAX_MP3S)) {
155                 if ((strlen(de->d_name) > 3) && !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3")) {
156                         strncpy(fns[files], de->d_name, sizeof(fns[files]) - 1);
157                         argv[argc++] = fns[files];
158                         files++;
159                 }
160         }
161         argv[argc] = NULL;
162         closedir(dir);
163         if (pipe(fds)) {        
164                 ast_log(LOG_WARNING, "Pipe failed\n");
165                 return -1;
166         }
167 #if 0
168         printf("%d files total, %d args total\n", files, argc);
169         {
170                 int x;
171                 for (x=0;argv[x];x++)
172                         printf("arg%d: %s\n", x, argv[x]);
173         }
174 #endif  
175         if (!files) {
176                 ast_log(LOG_WARNING, "Found no files in '%s'\n", class->dir);
177                 close(fds[0]);
178                 close(fds[1]);
179                 return -1;
180         }
181         class->pid = fork();
182         if (class->pid < 0) {
183                 close(fds[0]);
184                 close(fds[1]);
185                 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
186                 return -1;
187         }
188         if (!class->pid) {
189                 int x;
190                 close(fds[0]);
191                 /* Stdout goes to pipe */
192                 dup2(fds[1], STDOUT_FILENO);
193                 /* Close unused file descriptors */
194                 for (x=3;x<8192;x++)
195                         close(x);
196                 /* Child */
197                 chdir(class->dir);
198                 /* Default install is /usr/local/bin */
199                 execv(LOCAL_MPG_123, argv);
200                 /* Many places have it in /usr/bin */
201                 execv(MPG_123, argv);
202                 /* Check PATH as a last-ditch effort */
203                 execvp("mpg123", argv);
204                 ast_log(LOG_WARNING, "Exec failed: %s\n", strerror(errno));
205                 close(fds[1]);
206                 exit(1);
207         } else {
208                 /* Parent */
209                 close(fds[1]);
210         }
211         return fds[0];
212 }
213
214 static void *monmp3thread(void *data)
215 {
216 #define MOH_MS_INTERVAL         100
217
218         struct mohclass *class = data;
219         struct mohdata *moh;
220         char buf[8192];
221         short sbuf[8192];
222         int res, res2;
223         struct timeval tv;
224         struct timeval tv_tmp;
225         long error_sec, error_usec;
226         long delay;
227
228         tv_tmp.tv_sec = 0;
229         tv_tmp.tv_usec = 0;
230         tv.tv_sec = 0;
231         tv.tv_usec = 0;
232         error_sec = 0;
233         error_usec = 0;
234         for(;/* ever */;) {
235                 /* Spawn mp3 player if it's not there */
236                 if (class->srcfd < 0) {
237                         if ((class->srcfd = spawn_mp3(class)) < 0) {
238                                 ast_log(LOG_WARNING, "unable to spawn mp3player\n");
239                                 /* Try again later */
240                                 sleep(500);
241                         }
242                 }
243                 if (class->pseudofd > -1) {
244                         /* Pause some amount of time */
245                         res = read(class->pseudofd, buf, sizeof(buf));
246                 } else {
247                         /* Reliable sleep */
248                         if (gettimeofday(&tv_tmp, NULL) < 0) {
249                                 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
250                                 return NULL;
251                         }
252                         if (((unsigned long)(tv.tv_sec) > 0)&&((unsigned long)(tv.tv_usec) > 0)) {
253                                 if ((unsigned long)(tv_tmp.tv_usec) < (unsigned long)(tv.tv_usec)) {
254                                         tv_tmp.tv_usec += 1000000;
255                                         tv_tmp.tv_sec -= 1;
256                                 }
257                                 error_sec = (unsigned long)(tv_tmp.tv_sec) - (unsigned long)(tv.tv_sec);
258                                 error_usec = (unsigned long)(tv_tmp.tv_usec) - (unsigned long)(tv.tv_usec);
259                         } else {
260                                 error_sec = 0;
261                                 error_usec = 0;
262                         }
263                         if (error_sec * 1000 + error_usec / 1000 < MOH_MS_INTERVAL) {
264                                 tv.tv_sec = tv_tmp.tv_sec + (MOH_MS_INTERVAL/1000 - error_sec);
265                                 tv.tv_usec = tv_tmp.tv_usec + ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec);
266                                 delay = (MOH_MS_INTERVAL/1000 - error_sec) * 1000 +
267                                                         ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec) / 1000;
268                         } else {
269                                 ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
270                                 tv.tv_sec = tv_tmp.tv_sec;
271                                 tv.tv_usec = tv_tmp.tv_usec;
272                                 delay = 0;
273                         }
274                         if (tv.tv_usec > 1000000) {
275                                 tv.tv_sec++;
276                                 tv.tv_usec-= 1000000;
277                         }
278                         if (delay > 0)
279                                 usleep(delay * 1000);
280                         res = 800;              /* 800 samples */
281                 }
282                 if (!class->members)
283                         continue;
284                 /* Read mp3 audio */
285                 if ((res2 = read(class->srcfd, sbuf, res * 2)) != res * 2) {
286                         if (!res2) {
287                                 close(class->srcfd);
288                                 class->srcfd = -1;
289                                 if (class->pid) {
290                                         kill(class->pid, SIGKILL);
291                                         class->pid = 0;
292                                 }
293                         } else
294                                 ast_log(LOG_DEBUG, "Read %d bytes of audio while expecting %d\n", res2, res * 2);
295                         continue;
296                 }
297                 ast_mutex_lock(&moh_lock);
298                 moh = class->members;
299                 while(moh) {
300                         /* Write data */
301                         if ((res = write(moh->pipe[1], sbuf, res2)) != res2) 
302                                 if (option_debug)
303                                         ast_log(LOG_DEBUG, "Only wrote %d of %d bytes to pipe\n", res, res2);
304                         moh = moh->next;
305                 }
306                 ast_mutex_unlock(&moh_lock);
307         }
308         return NULL;
309 }
310
311 static int moh0_exec(struct ast_channel *chan, void *data)
312 {
313         if (ast_moh_start(chan, data)) {
314                 ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
315                 return -1;
316         }
317         while(!ast_safe_sleep(chan, 10000));
318         return -1;
319 }
320
321 static int moh1_exec(struct ast_channel *chan, void *data)
322 {
323         int res;
324         if (!data || !atoi(data)) {
325                 ast_log(LOG_WARNING, "WaitMusicOnHold requires an argument (number of seconds to wait)\n");
326                 return -1;
327         }
328         if (ast_moh_start(chan, NULL)) {
329                 ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
330                 return -1;
331         }
332         res = ast_safe_sleep(chan, atoi(data) * 1000);
333         ast_moh_stop(chan);
334         return res;
335 }
336
337 static int moh2_exec(struct ast_channel *chan, void *data)
338 {
339         if (!data || ast_strlen_zero(data)) {
340                 ast_log(LOG_WARNING, "SetMusicOnHold requires an argument (class)\n");
341                 return -1;
342         }
343         strncpy(chan->musicclass, data, sizeof(chan->musicclass) - 1);
344         return 0;
345 }
346
347 static struct mohclass *get_mohbyname(char *name)
348 {
349         struct mohclass *moh;
350         moh = mohclasses;
351         while(moh) {
352                 if (!strcasecmp(name, moh->class))
353                         return moh;
354                 moh = moh->next;
355         }
356         return NULL;
357 }
358
359 static struct mohdata *mohalloc(struct mohclass *cl)
360 {
361         struct mohdata *moh;
362         long flags;
363         moh = malloc(sizeof(struct mohdata));
364         if (!moh)
365                 return NULL;
366         memset(moh, 0, sizeof(struct mohdata));
367         if (pipe(moh->pipe)) {
368                 ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno));
369                 free(moh);
370                 return NULL;
371         }
372         /* Make entirely non-blocking */
373         flags = fcntl(moh->pipe[0], F_GETFL);
374         fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
375         flags = fcntl(moh->pipe[1], F_GETFL);
376         fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
377         moh->parent = cl;
378         moh->next = cl->members;
379         cl->members = moh;
380         return moh;
381 }
382
383 static void moh_release(struct ast_channel *chan, void *data)
384 {
385         struct mohdata *moh = data, *prev, *cur;
386         int oldwfmt;
387         ast_mutex_lock(&moh_lock);
388         /* Unlink */
389         prev = NULL;
390         cur = moh->parent->members;
391         while(cur) {
392                 if (cur == moh) {
393                         if (prev)
394                                 prev->next = cur->next;
395                         else
396                                 moh->parent->members = cur->next;
397                         break;
398                 }
399                 prev = cur;
400                 cur = cur->next;
401         }
402         ast_mutex_unlock(&moh_lock);
403         close(moh->pipe[0]);
404         close(moh->pipe[1]);
405         oldwfmt = moh->origwfmt;
406         free(moh);
407         if (chan) {
408                 if (oldwfmt && ast_set_write_format(chan, oldwfmt)) 
409                         ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(oldwfmt));
410                 if (option_verbose > 2)
411                         ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name);
412         }
413 }
414
415 static void *moh_alloc(struct ast_channel *chan, void *params)
416 {
417         struct mohdata *res;
418         struct mohclass *class;
419         ast_mutex_lock(&moh_lock);
420         class = get_mohbyname(params);
421         if (class)
422                 res = mohalloc(class);
423         else {
424                 if (strcasecmp(params, "default"))
425                         ast_log(LOG_WARNING, "No class: %s\n", (char *)params);
426                 res = NULL;
427         }
428         ast_mutex_unlock(&moh_lock);
429         if (res) {
430                 res->origwfmt = chan->writeformat;
431                 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
432                         ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format\n", chan->name);
433                         moh_release(NULL, res);
434                         res = NULL;
435                 }
436 #if 0
437                 /* Allow writes to interrupt */
438                 chan->writeinterrupt = 1;
439 #endif          
440                 if (option_verbose > 2)
441                         ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on %s\n", (char *)params, chan->name);
442         }
443         return res;
444 }
445
446 static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
447 {
448         struct ast_frame f;
449         struct mohdata *moh = data;
450         short buf[1280 + AST_FRIENDLY_OFFSET / 2];
451         int res;
452
453         len = samples * 2;
454         if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
455                 ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), (int)len, chan->name);
456                 len = sizeof(buf) - AST_FRIENDLY_OFFSET;
457         }
458         res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
459 #if 0
460         if (res != len) {
461                 ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno));
462         }
463 #endif
464         if (res > 0) {
465                 memset(&f, 0, sizeof(f));
466                 f.frametype = AST_FRAME_VOICE;
467                 f.subclass = AST_FORMAT_SLINEAR;
468                 f.mallocd = 0;
469                 f.datalen = res;
470                 f.samples = res / 2;
471                 f.data = buf + AST_FRIENDLY_OFFSET / 2;
472                 f.offset = AST_FRIENDLY_OFFSET;
473                 if (ast_write(chan, &f)< 0) {
474                         ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
475                         return -1;
476                 }
477         }
478         return 0;
479 }
480
481 static struct ast_generator mohgen = 
482 {
483         alloc: moh_alloc,
484         release: moh_release,
485         generate: moh_generate,
486 };
487
488 static int moh_register(char *classname, char *mode, char *param, char *miscargs)
489 {
490         struct mohclass *moh;
491 #ifdef ZAPATA_MOH
492         int x;
493 #endif
494         ast_mutex_lock(&moh_lock);
495         moh = get_mohbyname(classname);
496         ast_mutex_unlock(&moh_lock);
497         if (moh) {
498                 ast_log(LOG_WARNING, "Music on Hold '%s' already exists\n", classname);
499                 return -1;
500         }
501         moh = malloc(sizeof(struct mohclass));
502         if (!moh)
503                 return -1;
504         memset(moh, 0, sizeof(struct mohclass));
505
506         strncpy(moh->class, classname, sizeof(moh->class) - 1);
507         if (miscargs)
508                 strncpy(moh->miscargs, miscargs, sizeof(moh->miscargs) - 1);
509         if (!strcasecmp(mode, "mp3") || !strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb") || !strcasecmp(mode, "httpmp3")) {
510                 if (!strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3nb"))
511                         moh->single = 1;
512                 if (!strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb"))
513                         moh->quiet = 1;
514                 strncpy(moh->dir, param, sizeof(moh->dir) - 1);
515                 moh->srcfd = -1;
516 #ifdef ZAPATA_MOH
517                 /* It's an MP3 Moh -- Open /dev/zap/pseudo for timing...  Is
518                    there a better, yet reliable way to do this? */
519                 moh->pseudofd = open("/dev/zap/pseudo", O_RDONLY);
520                 if (moh->pseudofd < 0) {
521                         ast_log(LOG_WARNING, "Unable to open pseudo channel for timing...  Sound may be choppy.\n");
522                 } else {
523                         x = 320;
524                         ioctl(moh->pseudofd, ZT_SET_BLOCKSIZE, &x);
525                 }
526 #else
527                 moh->pseudofd = -1;
528 #endif
529                 if (pthread_create(&moh->thread, NULL, monmp3thread, moh)) {
530                         ast_log(LOG_WARNING, "Unable to create moh...\n");
531                         if (moh->pseudofd > -1)
532                                 close(moh->pseudofd);
533                         free(moh);
534                         return -1;
535                 }
536         } else {
537                 ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mode);
538                 free(moh);
539                 return -1;
540         }
541         ast_mutex_lock(&moh_lock);
542         moh->next = mohclasses;
543         mohclasses = moh;
544         ast_mutex_unlock(&moh_lock);
545         return 0;
546 }
547
548 int ast_moh_start(struct ast_channel *chan, char *class)
549 {
550         if (!class || ast_strlen_zero(class))
551                 class = chan->musicclass;
552         if (!class || ast_strlen_zero(class))
553                 class = "default";
554         return ast_activate_generator(chan, &mohgen, class);
555 }
556
557 void ast_moh_stop(struct ast_channel *chan)
558 {
559         ast_deactivate_generator(chan);
560 }
561
562 static void load_moh_classes(void)
563 {
564         struct ast_config *cfg;
565         struct ast_variable *var;
566         char *data;
567         char *args;
568         cfg = ast_load("musiconhold.conf");
569         if (cfg) {
570                 var = ast_variable_browse(cfg, "classes");
571                 while(var) {
572                         data = strchr(var->value, ':');
573                         if (data) {
574                                 *data = '\0';
575                                 data++;
576                                 args = strchr(data, ',');
577                                 if (args) {
578                                         *args = '\0';
579                                         args++;
580                                 }
581                                 moh_register(var->name, var->value, data,args);
582                         }
583                         var = var->next;
584                 }
585                 ast_destroy(cfg);
586         }
587 }
588
589 static void ast_moh_destroy(void)
590 {
591         struct mohclass *moh;
592         char buff[8192];
593         int bytes, tbytes=0, stime = 0;
594         if (option_verbose > 1)
595                 ast_verbose(VERBOSE_PREFIX_2 "Destroying any remaining musiconhold processes\n");
596         ast_mutex_lock(&moh_lock);
597         moh = mohclasses;
598         while(moh) {
599                 if (moh->pid) {
600                         ast_log(LOG_DEBUG, "killing %d!\n", moh->pid);
601                         stime = time(NULL);
602                         kill(moh->pid, SIGKILL);
603                         while ((bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime + 5) {
604                                 tbytes = tbytes + bytes;
605                         }
606                         ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", moh->pid, tbytes);
607                         close(moh->srcfd);
608                         moh->pid = 0;
609                 }
610                 moh = moh->next;
611         }
612         ast_mutex_unlock(&moh_lock);
613 }
614
615 int load_module(void)
616 {
617         int res;
618         load_moh_classes();
619         res = ast_register_application(app0, moh0_exec, synopsis0, descrip0);
620         ast_register_atexit(ast_moh_destroy);
621         if (!res)
622                 res = ast_register_application(app1, moh1_exec, synopsis1, descrip1);
623         if (!res)
624                 res = ast_register_application(app2, moh2_exec, synopsis2, descrip2);
625         return res;
626 }
627
628 int unload_module(void)
629 {
630         return -1;
631 }
632
633 char *description(void)
634 {
635         return "Music On Hold Resource";
636 }
637
638 int usecount(void)
639 {
640         /* Never allow Music On Hold to be unloaded
641            unresolve needed symbols in the dialer */
642 #if 0
643         int res;
644         STANDARD_USECOUNT(res);
645         return res;
646 #else
647         return 1;
648 #endif
649 }
650
651 char *key()
652 {
653         return ASTERISK_GPL_KEY;
654 }