Merge branch 'refs/heads/t/listen-address'
authorAndre Noll <maan@tuebingen.mpg.de>
Mon, 28 May 2018 16:29:06 +0000 (18:29 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Mon, 28 May 2018 16:31:26 +0000 (18:31 +0200)
A short series which adds options for para_server that allow the user
to specify the listening addresses of the passive sockets.

The resolution of the conflicts in server.c and send_common.c have
been well tested and were cooking for a couple of weeks.

* refs/heads/t/listen-address:
  server: Add --http-listen-address and --dccp-listen-address.
  server: Implement --listen-address for control service.

1  2 
NEWS.md
dccp_send.c
http_send.c
m4/lls/server.suite.m4
send.h
send_common.c
server.c

diff --cc NEWS.md
+++ b/NEWS.md
@@@ -1,23 -1,6 +1,26 @@@
  NEWS
  ====
  
 +-------------------------------------------
 +0.6.2 (to be accounced) "elastic diversity"
 +-------------------------------------------
 +
 +- para_gui no longer waits up to one second to update the screen when
 +  the geometry of the terminal changes.
 +- Minor documentation improvements.
 +- Improvements to the crypto subsystem.
 +- The server subcommand "task" has been deprecated. It still works,
 +  but prints nothing. It will be removed in the next major release.
 +- Server log output is now serialized, avoiding issues with partial
 +  lines.
 +- It is now possible to switch to a different afs database by changing
 +  the server configuration and sending SIGHUP to the server process.
++- New server options: --listen--address, --http-listen-address and
++  --dccp-listen-address. These options restrict the set of listening
++  addresses of the TCP and DCCP sockets of the server process.
 +
 +Download: [tarball](./releases/paraslash-git.tar.xz)
 +
  ----------------------------------------
  0.6.1 (2017-09-23) "segmented iteration"
  ----------------------------------------
diff --cc dccp_send.c
@@@ -218,13 -218,32 +221,14 @@@ static char *dccp_status(void
        return result;
  }
  
 -/**
 - * The init function of the dccp sender.
 - *
 - * \param s pointer to the dccp sender struct.
 - *
 - * It initializes all function pointers of \a s and starts
 - * listening on the given port.
 +/*
 + * Initialize the client list and the access control list and listen on the
 + * dccp port.
   */
 -void dccp_send_init(struct sender *s)
 +static void dccp_send_init(void)
  {
 -      s->status = dccp_status;
 -      s->send = NULL;
 -      s->pre_select = dccp_pre_select;
 -      s->post_select = dccp_post_select;
 -      s->shutdown_clients = dccp_shutdown_clients;
 -      s->resolve_target = NULL;
 -      s->help = generic_sender_help;
 -      s->client_cmds[SENDER_on] = dccp_com_on;
 -      s->client_cmds[SENDER_off] = dccp_com_off;
 -      s->client_cmds[SENDER_deny] = dccp_com_deny;
 -      s->client_cmds[SENDER_allow] = dccp_com_allow;
 -      s->client_cmds[SENDER_add] = NULL;
 -      s->client_cmds[SENDER_delete] = NULL;
 -
        init_sender_status(dss, OPT_RESULT(DCCP_ACCESS),
+               OPT_RESULT(DCCP_LISTEN_ADDRESS),
                OPT_UINT32_VAL(DCCP_PORT), OPT_UINT32_VAL(DCCP_MAX_CLIENTS),
                OPT_GIVEN(DCCP_DEFAULT_DENY));
        generic_com_on(dss, IPPROTO_DCCP);
diff --cc http_send.c
@@@ -241,13 -239,32 +244,14 @@@ static char *http_status(void
        return generic_sender_status(hss, "http");
  }
  
 -/**
 - * The init function of the http sender.
 - *
 - * \param s Pointer to the http sender struct.
 - *
 - * It initializes all function pointers of \a s, the client list and the access
 - * control list. If the autostart option was given, the tcp port is opened.
 +/*
 + * Initialize the client list and the access control list, and optionally
 + * listen on the tcp port.
   */
 -void http_send_init(struct sender *s)
 +static void http_send_init(void)
  {
 -      s->status = http_status;
 -      s->send = http_send;
 -      s->pre_select = http_pre_select;
 -      s->post_select = http_post_select;
 -      s->shutdown_clients = http_shutdown_clients;
 -      s->resolve_target = NULL;
 -      s->help = generic_sender_help;
 -      s->client_cmds[SENDER_on] = http_com_on;
 -      s->client_cmds[SENDER_off] = http_com_off;
 -      s->client_cmds[SENDER_deny] = http_com_deny;
 -      s->client_cmds[SENDER_allow] = http_com_allow;
 -      s->client_cmds[SENDER_add] = NULL;
 -      s->client_cmds[SENDER_delete] = NULL;
 -
        init_sender_status(hss, OPT_RESULT(HTTP_ACCESS),
+               OPT_RESULT(HTTP_LISTEN_ADDRESS),
                OPT_UINT32_VAL(HTTP_PORT), OPT_UINT32_VAL(HTTP_MAX_CLIENTS),
                OPT_GIVEN(HTTP_DEFAULT_DENY));
        if (OPT_GIVEN(HTTP_NO_AUTOSTART))
Simple merge
diff --cc send.h
Simple merge
diff --cc send_common.c
Simple merge
diff --cc server.c
+++ b/server.c
@@@ -109,30 -106,11 +109,31 @@@ static struct signal_task *signal_task
  /** The process id of the audio file selector process. */
  pid_t afs_pid = 0;
  
 +/* The the main server process (parent of afs and the command handlers). */
 +static pid_t server_pid;
 +
 +/**
 + * Tell whether the executing process is a command handler.
 + *
 + * Cleanup on exit must be performed differently for command handlers.
 + *
 + * \return True if the pid of the executing process is neither the server pid
 + * nor the afs pid.
 + */
 +bool process_is_command_handler(void)
 +{
 +      pid_t pid = getpid();
 +
 +      return pid != afs_pid && pid != server_pid;
 +}
 +
  /** 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. */
        int argc;
        /** Argument vector passed to para_server's main function. */
@@@ -382,22 -347,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, fd_set *rfds,
++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], 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 -413,61 +460,63 @@@ out
        return 0;
  }
  
 -              ret = command_task_accept(n, &s->rfds, sct);
+ 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++) {
 -static void init_server_command_task(int argc, char **argv)
++              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;
 -      static struct server_command_task server_command_task_struct,
 -              *sct = &server_command_task_struct;
+       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,