*
*/
+#include <signal.h>
+#include <sys/types.h>
+#include <dirent.h>
-
+#include "para.h"
+#include "error.h"
#include "server.cmdline.h"
+#include "afh.h"
+#include "string.h"
#include "afs.h"
#include "server.h"
#include "vss.h"
#include "config.h"
#include "close_on_fork.h"
#include "send.h"
-#include "error.h"
#include "net.h"
#include "daemon.h"
-#include "string.h"
#include "ipc.h"
#include "fd.h"
+#include "list.h"
+#include "sched.h"
#include "signal.h"
#include "user_list.h"
extern void http_send_init(struct sender *);
extern void ortp_send_init(struct sender *);
-/* TODO: This is better handled by autoconf */
-/** the list of supported audio file selectors */
-struct audio_file_selector selectors[] = {
- {
- .name = "random",
- .init = random_selector_init,
- .update_audio_file = NULL,
- },
- {
- .name = "playlist",
- .init = playlist_selector_init,
- .update_audio_file = NULL,
- .pre_select = NULL,
- .post_select = NULL,
- },
-#ifdef HAVE_MYSQL
- {
- .name = "mysql",
- .init = mysql_selector_init,
- .update_audio_file = NULL,
- .pre_select = NULL,
- .post_select = NULL,
- },
-#endif
- {
- .name = NULL,
- }
-};
-
/** the list of supported senders */
struct sender senders[] = {
{
goto err_out;
mmd_mutex = ret;
- mmd->selector_num = 0;
mmd->num_played = 0;
mmd->num_commands = 0;
mmd->events = 0;
}
if (!ret) {
int tmp = conf.daemon_given;
- server_cmdline_parser_configfile(cf, &conf, override, 0, 0);
+ struct server_cmdline_parser_params params = {
+ .override = override,
+ .initialize = 0,
+ .check_required = 0,
+ .check_ambiguity = 0
+ };
+ server_cmdline_parser_config_file(cf, &conf, ¶ms);
conf.daemon_given = tmp;
}
/* logfile */
}
}
-static void init_selector(void)
-{
- int i, ret;
-
- mmd->selector_change = -1; /* no change nec., set to new num by com_chs */
- if (!conf.selector_given)
- goto random;
- for (i = 0; selectors[i].name; i++) {
- if (strcmp(selectors[i].name, conf.selector_arg))
- continue;
- PARA_NOTICE_LOG("initializing %s audio file selector\n",
- selectors[i].name);
- ret = selectors[i].init(&selectors[i]);
- if (ret < 0) {
- PARA_WARNING_LOG("%s", PARA_STRERROR(-ret));
- break;
- }
- mmd->selector_num = i;
- return;
- }
- PARA_WARNING_LOG("%s", "falling back to the random selector\n");
-random:
- mmd->selector_num = 0;
- selectors[0].init(&selectors[0]); /* always successful */
-}
-
static unsigned init_network(void)
{
int fd, ret = init_tcp_socket(conf.port_arg);
exit(EXIT_FAILURE);
}
+uint32_t afs_socket_cookie;
+int afs_socket;
+static pid_t afs_pid;
+
+static void init_afs(void)
+{
+ int ret, afs_server_socket[2];
+
+ ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, afs_server_socket);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ afs_socket_cookie = para_random((uint32_t)-1);
+ afs_pid = fork();
+ if (afs_pid < 0)
+ exit(EXIT_FAILURE);
+ if (!afs_pid) { /* child (afs) */
+ close(afs_server_socket[0]);
+ afs_init(afs_socket_cookie, afs_server_socket[1]);
+ }
+ close(afs_server_socket[1]);
+ afs_socket = afs_server_socket[0];
+ ret = mark_fd_nonblock(afs_socket);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ add_close_on_fork_list(afs_socket);
+ PARA_INFO_LOG("afs_socket: %d, afs_socket_cookie: %u\n", afs_socket,
+ (unsigned) afs_socket_cookie);
+}
+
+
static unsigned do_inits(int argc, char **argv)
{
/* connector's address information */
/* become daemon */
if (conf.daemon_given)
daemon_init();
- init_selector();
-// PARA_ERROR_LOG("num: %d\n", mmd->selector_num);
PARA_NOTICE_LOG("%s", "initializing virtual streaming system\n");
+ afh_init();
vss_init();
mmd->server_pid = getpid();
setup_signal_handling();
+ init_afs();
mmd_lock();
/* init network socket */
PARA_NOTICE_LOG("%s", "initializing tcp command socket\n");
return sockfd;
}
-static void change_selector(void)
-{
- int ret, old = mmd->selector_num, new = mmd->selector_change;
-
- selectors[old].shutdown();
- ret = selectors[new].init(&selectors[new]);
- mmd->selector_change = -1; /* reset */
- if (ret >= 0) {
- mmd->selector_num = new;
- return;
- }
- /* init failed */
- PARA_ERROR_LOG("%s -- switching to the random selector\n", PARA_STRERROR(-ret));
- selectors[0].init(&selectors[0]);
- mmd->selector_num = 0;
-}
-
/*
* called when server gets SIGHUP or when client invokes hup command.
*/
close_log(logfile); /* gets reopened if necessary by parse_config */
logfile = NULL;
parse_config(1); /* reopens log */
- mmd->selector_change = mmd->selector_num; /* do not change selector.. */
- change_selector(); /* .. just reload */
init_user_list(user_list_file); /* reload user list */
+ if (afs_pid)
+ kill(afs_pid, SIGHUP);
}
static void status_refresh(void)
/* check socket and signal pipe in any case */
para_fd_set(sockfd, &rfds, &max_fileno);
para_fd_set(signal_pipe, &rfds, &max_fileno);
- timeout = vss_preselect();
+ timeout = vss_preselect(&rfds, &wfds, &max_fileno);
status_refresh();
for (i = 0; senders[i].name; i++) {
if (senders[i].status != SENDER_ON)
continue;
if (!senders[i].pre_select)
continue;
- senders[i].pre_select( &max_fileno, &rfds, &wfds);
- }
- if (selectors[mmd->selector_num].pre_select) {
- ret = selectors[mmd->selector_num].pre_select(&rfds, &wfds);
- max_fileno = PARA_MAX(max_fileno, ret);
+ senders[i].pre_select(&max_fileno, &rfds, &wfds);
}
mmd_unlock();
ret = para_select(max_fileno + 1, &rfds, &wfds, timeout);
mmd_lock();
- if (mmd->selector_change >= 0)
- change_selector();
- if (selectors[mmd->selector_num].post_select)
- selectors[mmd->selector_num].post_select(&rfds, &wfds);
+ vss_post_select(&rfds, &wfds);
if (ret < 0)
goto repeat;
for (i = 0; senders[i].name; i++) {
status_refresh();
if (FD_ISSET(signal_pipe, &rfds)) {
int sig;
+ pid_t pid;
sig = para_next_signal();
switch (sig) {
case SIGHUP:
handle_sighup();
break;
case SIGCHLD:
- para_reap_children();
+ for (;;) {
+ ret = para_reap_child(&pid);
+ if (ret <= 0)
+ break;
+ if (pid != afs_pid)
+ continue;
+ PARA_EMERG_LOG("fatal: afs died\n");
+ goto genocide;
+ }
break;
/* die on sigint/sigterm. Kill all children too. */
case SIGINT:
case SIGTERM:
PARA_EMERG_LOG("terminating on signal %d\n", sig);
+genocide:
kill(0, SIGTERM);
- selectors[mmd->selector_num].shutdown();
mutex_destroy(mmd_mutex);
shm_detach(mmd);
shm_destroy(mmd_shm_id);
+
exit(EXIT_FAILURE);
}
}