]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
master: Changed passing of listener settings from master to process to be more flexible.
authorTimo Sirainen <tss@iki.fi>
Tue, 18 Aug 2015 17:23:45 +0000 (20:23 +0300)
committerTimo Sirainen <tss@iki.fi>
Tue, 18 Aug 2015 17:23:45 +0000 (20:23 +0300)
This is needed to allow adding new listener settings, such as `haproxy'.
Patch by Stephan Bosch - with some small changes.

src/lib-master/master-service-private.h
src/lib-master/master-service.c
src/master/service-process.c

index 0d4354195ea37b5d23b7ed8421dd105fd511855d..8b2abbccafc700db3fa04b602b30734a13d4fbdd 100644 (file)
@@ -6,10 +6,14 @@
 
 struct master_service_listener {
        struct master_service *service;
-       int fd;
+       char *name;
+
+       /* settings */
        bool ssl;
+
+       /* state */
+       int fd; 
        struct io *io;
-       const char *name;
 };
 
 struct master_service {
@@ -28,10 +32,8 @@ struct master_service {
        int config_fd;
        int syslog_facility;
 
-       unsigned int socket_count, ssl_socket_count;
        struct master_service_listener *listeners;
-       char **listener_names;
-       unsigned int listener_names_count;
+       unsigned int socket_count;
 
        struct io *io_status_write, *io_status_error;
        unsigned int service_count_left;
index 7b6005467eae8f20ed5cb535cfb3e8e184fc8233..3ae243418900640d6cd97e18828daf06d4adca47 100644 (file)
@@ -106,13 +106,53 @@ static void master_service_verify_version_string(struct master_service *service)
        }
 }
 
+static void master_service_init_socket_listeners(struct master_service *service)
+{
+       unsigned int i;
+       const char *value;
+       bool have_ssl_sockets = FALSE;
+
+       if (service->socket_count == 0)
+               return;
+
+       service->listeners =
+               i_new(struct master_service_listener, service->socket_count);
+
+       for (i = 0; i < service->socket_count; i++) {
+               struct master_service_listener *l = &service->listeners[i];
+
+               l->service = service;
+               l->fd = MASTER_LISTEN_FD_FIRST + i;
+
+               value = getenv(t_strdup_printf("SOCKET%u_SETTINGS", i));
+               if (value != NULL) {
+                       const char *const *settings =
+                               t_strsplit_tabescaped(value);
+
+                       if (*settings != NULL) {
+                               l->name = i_strdup_empty(*settings);
+                               settings++;
+                       }
+                       while (*settings != NULL) {
+                               if (strcmp(*settings, "ssl") == 0) {
+                                       l->ssl = TRUE;
+                                       have_ssl_sockets = TRUE;
+                               }
+                               settings++;
+                       }
+               }
+       }
+       service->want_ssl_settings = have_ssl_sockets ||
+               (service->flags & MASTER_SERVICE_FLAG_USE_SSL_SETTINGS) != 0;
+}
+
 struct master_service *
 master_service_init(const char *name, enum master_service_flags flags,
                    int *argc, char **argv[], const char *getopt_str)
 {
        struct master_service *service;
-       const char *value;
        unsigned int count;
+       const char *value;
 
        i_assert(name != NULL);
 
@@ -177,21 +217,14 @@ master_service_init(const char *name, enum master_service_flags flags,
        } else {
                service->version_string = PACKAGE_VERSION;
        }
+
+       /* listener configuration */
        value = getenv("SOCKET_COUNT");
        if (value != NULL)
                service->socket_count = atoi(value);
-       value = getenv("SSL_SOCKET_COUNT");
-       if (value != NULL)
-               service->ssl_socket_count = atoi(value);
-       value = getenv("SOCKET_NAMES");
-       if (value != NULL) {
-               service->listener_names =
-                       p_strsplit_tabescaped(default_pool, value);
-               service->listener_names_count =
-                       str_array_length((void *)service->listener_names);
-       }
-       service->want_ssl_settings = service->ssl_socket_count > 0 ||
-               (flags & MASTER_SERVICE_FLAG_USE_SSL_SETTINGS) != 0;
+       T_BEGIN {
+               master_service_init_socket_listeners(service);
+       } T_END;
 
        /* set up some kind of logging until we know exactly how and where
           we want to log */
@@ -574,8 +607,9 @@ const char *master_service_get_socket_name(struct master_service *service,
        i_assert(listen_fd >= MASTER_LISTEN_FD_FIRST);
 
        i = listen_fd - MASTER_LISTEN_FD_FIRST;
-       return i < service->listener_names_count ?
-               service->listener_names[i] : "";
+       i_assert(i < service->socket_count);
+       return service->listeners[i].name != NULL ?
+               service->listeners[i].name : "";
 }
 
 void master_service_set_avail_overflow_callback(struct master_service *service,
@@ -807,6 +841,7 @@ void master_service_close_config_fd(struct master_service *service)
 void master_service_deinit(struct master_service **_service)
 {
        struct master_service *service = *_service;
+       unsigned int i;
 
        *_service = NULL;
 
@@ -836,8 +871,8 @@ void master_service_deinit(struct master_service **_service)
        lib_atexit_run();
        io_loop_destroy(&service->ioloop);
 
-       if (service->listener_names != NULL)
-               p_strsplit_free(default_pool, service->listener_names);
+       for (i = 0; i < service->socket_count; i++)
+               i_free(service->listeners[i].name);
        i_free(service->listeners);
        i_free(service->getopt_str);
        i_free(service->name);
@@ -912,29 +947,6 @@ static void master_service_listen(struct master_service_listener *l)
        master_service_client_connection_callback(service, &conn);
 }
 
-static void io_listeners_init(struct master_service *service)
-{
-       unsigned int i;
-
-       if (service->socket_count == 0)
-               return;
-
-       service->listeners =
-               i_new(struct master_service_listener, service->socket_count);
-
-       for (i = 0; i < service->socket_count; i++) {
-               struct master_service_listener *l = &service->listeners[i];
-
-               l->service = service;
-               l->fd = MASTER_LISTEN_FD_FIRST + i;
-               l->name = i < service->listener_names_count ?
-                       service->listener_names[i] : "";
-
-               if (i >= service->socket_count - service->ssl_socket_count)
-                       l->ssl = TRUE;
-       }
-}
-
 void master_service_io_listeners_add(struct master_service *service)
 {
        unsigned int i;
@@ -942,9 +954,6 @@ void master_service_io_listeners_add(struct master_service *service)
        if (service->stopping)
                return;
 
-       if (service->listeners == NULL)
-               io_listeners_init(service);
-
        for (i = 0; i < service->socket_count; i++) {
                struct master_service_listener *l = &service->listeners[i];
 
@@ -959,11 +968,9 @@ void master_service_io_listeners_remove(struct master_service *service)
 {
        unsigned int i;
 
-       if (service->listeners != NULL) {
-               for (i = 0; i < service->socket_count; i++) {
-                       if (service->listeners[i].io != NULL)
-                               io_remove(&service->listeners[i].io);
-               }
+       for (i = 0; i < service->socket_count; i++) {
+               if (service->listeners[i].io != NULL)
+                       io_remove(&service->listeners[i].io);
        }
 }
 
@@ -971,12 +978,10 @@ void master_service_ssl_io_listeners_remove(struct master_service *service)
 {
        unsigned int i;
 
-       if (service->listeners != NULL) {
-               for (i = 0; i < service->socket_count; i++) {
-                       if (service->listeners[i].io != NULL &&
-                           service->listeners[i].ssl)
-                               io_remove(&service->listeners[i].io);
-               }
+       for (i = 0; i < service->socket_count; i++) {
+               if (service->listeners[i].io != NULL &&
+                   service->listeners[i].ssl)
+                       io_remove(&service->listeners[i].io);
        }
 }
 
@@ -984,24 +989,15 @@ static void master_service_io_listeners_close(struct master_service *service)
 {
        unsigned int i;
 
-       if (service->listeners != NULL) {
-               /* close via listeners. some fds might be pipes that are
-                  currently handled as clients. we don't want to close them. */
-               for (i = 0; i < service->socket_count; i++) {
-                       if (service->listeners[i].fd != -1) {
-                               if (close(service->listeners[i].fd) < 0) {
-                                       i_error("close(listener %d) failed: %m",
-                                               service->listeners[i].fd);
-                               }
-                               service->listeners[i].fd = -1;
+       /* close via listeners. some fds might be pipes that are
+          currently handled as clients. we don't want to close them. */
+       for (i = 0; i < service->socket_count; i++) {
+               if (service->listeners[i].fd != -1) {
+                       if (close(service->listeners[i].fd) < 0) {
+                               i_error("close(listener %d) failed: %m",
+                                       service->listeners[i].fd);
                        }
-               }
-       } else {
-               for (i = 0; i < service->socket_count; i++) {
-                       int fd = MASTER_LISTEN_FD_FIRST + i;
-
-                       if (close(fd) < 0)
-                               i_error("close(listener %d) failed: %m", fd);
+                       service->listeners[i].fd = -1;
                }
        }
 }
index dbe7fd7fe0cc555263fd0302beccaf275d22c692..6198423cd09cb7ec4c0e27870329d6b86360aefb 100644 (file)
@@ -58,9 +58,9 @@ service_dup_fds(struct service *service)
 {
        struct service_listener *const *listeners;
        ARRAY_TYPE(dup2) dups;
-       string_t *listener_names;
+       string_t *listener_settings;
        int fd = MASTER_LISTEN_FD_FIRST;
-       unsigned int i, count, socket_listener_count, ssl_socket_count;
+       unsigned int i, count, socket_listener_count;
 
        /* stdin/stdout is already redirected to /dev/null. Other master fds
           should have been opened with fd_close_on_exec() so we don't have to
@@ -72,7 +72,6 @@ service_dup_fds(struct service *service)
         socket_listener_count = 0;
        listeners = array_get(&service->listeners, &count);
        t_array_init(&dups, count + 10);
-       listener_names = t_str_new(256);
 
        switch (service->type) {
        case SERVICE_TYPE_LOG:
@@ -94,32 +93,23 @@ service_dup_fds(struct service *service)
                break;
        }
 
-       /* anvil/log fds have no names */
-       for (i = MASTER_LISTEN_FD_FIRST; i < (unsigned int)fd; i++)
-               str_append_c(listener_names, '\t');
-
-       /* first add non-ssl listeners */
+       /* add listeners */
+       listener_settings = t_str_new(256);
        for (i = 0; i < count; i++) {
-               if (listeners[i]->fd != -1 &&
-                   (listeners[i]->type != SERVICE_LISTENER_INET ||
-                    !listeners[i]->set.inetset.set->ssl)) {
-                       str_append_tabescaped(listener_names, listeners[i]->name);
-                       str_append_c(listener_names, '\t');
-                       dup2_append(&dups, listeners[i]->fd, fd++);
-                       socket_listener_count++;
-               }
-       }
-       /* then ssl-listeners */
-       ssl_socket_count = 0;
-       for (i = 0; i < count; i++) {
-               if (listeners[i]->fd != -1 &&
-                   listeners[i]->type == SERVICE_LISTENER_INET &&
-                   listeners[i]->set.inetset.set->ssl) {
-                       str_append_tabescaped(listener_names, listeners[i]->name);
-                       str_append_c(listener_names, '\t');
+               if (listeners[i]->fd != -1) {
+                       str_truncate(listener_settings, 0);
+                       str_append_tabescaped(listener_settings, listeners[i]->name);
+
+                       if (listeners[i]->type == SERVICE_LISTENER_INET) {
+                               if (listeners[i]->set.inetset.set->ssl)
+                                       str_append(listener_settings, "\tssl");
+                       }
+                       
                        dup2_append(&dups, listeners[i]->fd, fd++);
+
+                       env_put(t_strdup_printf("SOCKET%d_SETTINGS=%s",
+                               socket_listener_count, str_c(listener_settings)));
                        socket_listener_count++;
-                       ssl_socket_count++;
                }
        }
 
@@ -174,8 +164,6 @@ service_dup_fds(struct service *service)
 
        i_assert(fd == MASTER_LISTEN_FD_FIRST + (int)socket_listener_count);
        env_put(t_strdup_printf("SOCKET_COUNT=%d", socket_listener_count));
-       env_put(t_strdup_printf("SSL_SOCKET_COUNT=%d", ssl_socket_count));
-       env_put(t_strdup_printf("SOCKET_NAMES=%s", str_c(listener_names)));
 }
 
 static void