]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - server.c
Merge branch 'refs/heads/t/listen-address'
[paraslash.git] / server.c
index e5335346010313277e258b3d2bb0a0c9f108fbfc..a344b77440751a6e7017d9d7e641390a36eb157f 100644 (file)
--- a/server.c
+++ b/server.c
@@ -45,6 +45,7 @@
 #include "afh.h"
 #include "string.h"
 #include "afs.h"
+#include "net.h"
 #include "server.h"
 #include "list.h"
 #include "send.h"
@@ -52,7 +53,6 @@
 #include "vss.h"
 #include "config.h"
 #include "close_on_fork.h"
-#include "net.h"
 #include "daemon.h"
 #include "ipc.h"
 #include "fd.h"
@@ -129,8 +129,9 @@ bool process_is_command_handler(void)
 
 /** The task responsible for server command handling. */
 struct server_command_task {
-       /** TCP port on which para_server listens for connections. */
-       int listen_fd;
+       unsigned num_listen_fds; /* only one by default */
+       /** TCP socket(s) on which para_server listens for connections. */
+       int *listen_fds;
        /* File descriptor for the accepted socket. */
        int child_fd;
        /** Copied from para_server's main function. */
@@ -382,22 +383,22 @@ static void init_signal_task(void)
 
 static void command_pre_select(struct sched *s, void *context)
 {
+       unsigned n;
        struct server_command_task *sct = context;
-       para_fd_set(sct->listen_fd, &s->rfds, &s->max_fileno);
+
+       for (n = 0; n < sct->num_listen_fds; n++)
+               para_fd_set(sct->listen_fds[n], &s->rfds, &s->max_fileno);
 }
 
-static int command_post_select(struct sched *s, void *context)
+static int command_task_accept(unsigned listen_idx, struct sched *s,
+               struct server_command_task *sct)
 {
-       struct server_command_task *sct = context;
        int new_fd, ret, i;
        char *peer_name;
        pid_t child_pid;
        uint32_t *chunk_table;
 
-       ret = task_get_notification(sct->task);
-       if (ret < 0)
-               return ret;
-       ret = para_accept(sct->listen_fd, &s->rfds, NULL, 0, &new_fd);
+       ret = para_accept(sct->listen_fds[listen_idx], &s->rfds, NULL, 0, &new_fd);
        if (ret <= 0)
                goto out;
        mmd->num_connects++;
@@ -459,23 +460,63 @@ out:
        return 0;
 }
 
+static int command_post_select(struct sched *s, void *context)
+{
+       struct server_command_task *sct = context;
+       unsigned n;
+       int ret;
+
+       ret = task_get_notification(sct->task);
+       if (ret < 0)
+               return ret;
+       for (n = 0; n < sct->num_listen_fds; n++) {
+               ret = command_task_accept(n, s, sct);
+               if (ret < 0) {
+                       free(sct->listen_fds);
+                       return ret;
+               }
+       }
+       return 0;
+}
+
 static void init_server_command_task(struct server_command_task *sct,
                int argc, char **argv)
 {
        int ret;
+       unsigned n;
+       uint32_t port = OPT_UINT32_VAL(PORT);
 
        PARA_NOTICE_LOG("initializing tcp command socket\n");
        sct->child_fd = -1;
        sct->argc = argc;
        sct->argv = argv;
-       ret = para_listen_simple(IPPROTO_TCP, OPT_UINT32_VAL(PORT));
-       if (ret < 0)
-               goto err;
-       sct->listen_fd = ret;
-       ret = mark_fd_nonblocking(sct->listen_fd);
-       if (ret < 0)
-               goto err;
-       add_close_on_fork_list(sct->listen_fd); /* child doesn't need the listener */
+       if (!OPT_GIVEN(LISTEN_ADDRESS)) {
+               sct->num_listen_fds = 1;
+               sct->listen_fds = para_malloc(sizeof(int));
+               ret = para_listen_simple(IPPROTO_TCP, port);
+               if (ret < 0)
+                       goto err;
+               sct->listen_fds[0] = ret;
+       } else {
+               sct->num_listen_fds = OPT_GIVEN(LISTEN_ADDRESS);
+               sct->listen_fds = para_malloc(sct->num_listen_fds * sizeof(int));
+               for (n = 0; n < OPT_GIVEN(LISTEN_ADDRESS); n++) {
+                       const char *arg;
+                       arg = lls_string_val(n, OPT_RESULT(LISTEN_ADDRESS));
+                       ret = para_listen(IPPROTO_TCP, arg, port);
+                       if (ret < 0)
+                               goto err;
+                       sct->listen_fds[n] = ret;
+               }
+       }
+       for (n = 0; n < sct->num_listen_fds; n++) {
+               ret = mark_fd_nonblocking(sct->listen_fds[n]);
+               if (ret < 0)
+                       goto err;
+               /* child doesn't need the listener */
+               add_close_on_fork_list(sct->listen_fds[n]);
+       }
+
        sct->task = task_register(&(struct task_info) {
                .name = "server command",
                .pre_select = command_pre_select,
@@ -505,6 +546,7 @@ static int init_afs(int argc, char **argv)
                int i;
 
                afs_pid = getpid();
+               crypt_shutdown();
                user_list_deplete();
                for (i = argc - 1; i >= 0; i--)
                        memset(argv[i], 0, strlen(argv[i]));
@@ -564,7 +606,7 @@ static void server_init(int argc, char **argv, struct server_command_task *sct)
        if (OPT_GIVEN(DAEMON))
                daemon_pipe = daemonize(true /* parent waits for SIGTERM */);
        server_pid = getpid();
-       init_random_seed_or_die();
+       crypt_init();
        daemon_log_welcome("server");
        init_ipc_or_die(); /* init mmd struct, mmd and log mutex */
        daemon_set_start_time();
@@ -643,6 +685,21 @@ static int server_select(int max_fileno, fd_set *readfds, fd_set *writefds,
        return ret;
 }
 
+/**
+ * Deallocate all lopsub parse results.
+ *
+ * The server allocates a parse result for command line options and optionally
+ * a second parse result for the effective configuration, defined by merging
+ * the command line options with the options stored in the configuration file.
+ * This function frees both structures.
+ */
+void free_lpr(void)
+{
+       lls_free_parse_result(server_lpr, CMD_PTR);
+       if (server_lpr != cmdline_lpr)
+               lls_free_parse_result(cmdline_lpr, CMD_PTR);
+}
+
 /**
  * The main function of para_server.
  *
@@ -669,12 +726,12 @@ int main(int argc, char *argv[])
         */
        mutex_unlock(mmd_mutex);
        sched_shutdown(&sched);
+       crypt_shutdown();
        signal_shutdown(signal_task);
        if (!process_is_command_handler()) { /* parent (server) */
                mutex_destroy(mmd_mutex);
                daemon_set_hooks(NULL, NULL); /* only one process remaining */
                mutex_destroy(log_mutex);
-               shm_detach(mmd);
                deplete_close_on_fork_list();
                if (ret < 0)
                        PARA_EMERG_LOG("%s\n", para_strerror(-ret));
@@ -686,8 +743,6 @@ int main(int argc, char *argv[])
        vss_shutdown();
        shm_detach(mmd);
        user_list_deplete();
-       lls_free_parse_result(server_lpr, CMD_PTR);
-       if (server_lpr != cmdline_lpr)
-               lls_free_parse_result(cmdline_lpr, CMD_PTR);
+       free_lpr();
        exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS);
 }