]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
director: Tell login proxy to notify director of open connections every director_user...
authorTimo Sirainen <tss@iki.fi>
Wed, 19 May 2010 10:23:32 +0000 (12:23 +0200)
committerTimo Sirainen <tss@iki.fi>
Wed, 19 May 2010 10:23:32 +0000 (12:23 +0200)
--HG--
branch : HEAD

doc/example-config/conf.d/10-director.conf
src/director/Makefile.am
src/director/director-settings.c
src/director/login-connection.c
src/director/main.c
src/director/notify-connection.c [new file with mode: 0644]
src/director/notify-connection.h [new file with mode: 0644]

index 0361c8559c9256cf84fbe3fde139379722e7e713..dceaa46a64d94275d8331398478de676bccffff5 100644 (file)
 # List of IPs or hostnames to all director servers, including ourself.
 # Ports can be specified as ip:port. The default port is the same as
 # what director service's inet_listener is using.
-director_servers = 
+#director_servers = 
 
 # List of IPs or hostnames to all backend mail servers. Ranges are allowed
 # too, like 10.0.0.10-10.0.0.30.
-director_mail_servers = 
+#director_mail_servers = 
 
 # How long to redirect users to a specific server after it no longer has
 # any connections.
-director_user_expire = 15 min
+#director_user_expire = 15 min
 
-# To enable director service, uncomment the mode and assign a port.
+# To enable director service, uncomment the modes and assign a port.
 service director {
   unix_listener login/director {
     #mode = 0666
   }
+  fifo_listener login/proxy-notify {
+    #mode = 0666
+  }
   inet_listener {
     #port = 
   }
index eee9f977fc183165759a7006fa523a0cf0dbb00b..9ac2b04d508f5d36e9e9d4b355212f5684950e66 100644 (file)
@@ -23,6 +23,7 @@ director_SOURCES = \
        doveadm-connection.c \
        login-connection.c \
        mail-host.c \
+       notify-connection.c \
        user-directory.c
 
 noinst_HEADERS = \
@@ -35,4 +36,5 @@ noinst_HEADERS = \
        doveadm-connection.h \
        login-connection.h \
        mail-host.h \
+       notify-connection.h \
        user-directory.h
index 37d3d5f0a8f4f13d3d7d46a8656e611e664188a6..3af1ef6ccf49668d925bcc1a4925bece61911258 100644 (file)
@@ -19,6 +19,16 @@ static buffer_t director_unix_listeners_buf = {
        director_unix_listeners,
        sizeof(director_unix_listeners), { 0, }
 };
+static struct file_listener_settings director_fifo_listeners_array[] = {
+       { "login/proxy-notify", 0, "", "" }
+};
+static struct file_listener_settings *director_fifo_listeners[] = {
+       &director_fifo_listeners_array[0]
+};
+static buffer_t director_fifo_listeners_buf = {
+       director_fifo_listeners,
+       sizeof(director_fifo_listeners), { 0, }
+};
 /* </settings checks> */
 
 struct service_settings director_service_settings = {
@@ -42,7 +52,8 @@ struct service_settings director_service_settings = {
 
        .unix_listeners = { { &director_unix_listeners_buf,
                              sizeof(director_unix_listeners[0]) } },
-       .fifo_listeners = ARRAY_INIT,
+       .fifo_listeners = { { &director_fifo_listeners_buf,
+                             sizeof(director_fifo_listeners[0]) } },
        .inet_listeners = ARRAY_INIT
 };
 #undef DEF
index 4c3f1ad3dcec12e82172e8a61423807207dffaa4..43a782513964d8727da75b1792b07e6bd5299dad 100644 (file)
@@ -71,12 +71,16 @@ login_connection_send_line(struct login_connection *conn, const char *line)
 static void login_host_callback(const struct ip_addr *ip, void *context)
 {
        struct login_host_request *request = context;
+       struct director *dir = request->conn->dir;
        const char *line;
+       unsigned int secs;
 
        T_BEGIN {
                if (ip != NULL) {
-                       line = t_strconcat(request->line, "\thost=",
-                                          net_ip2addr(ip), NULL);
+                       secs = dir->set->director_user_expire / 2;
+                       line = t_strdup_printf("%s\thost=%s\tproxy_refresh=%u",
+                                              request->line, net_ip2addr(ip),
+                                              secs);
                } else {
                        i_assert(strncmp(request->line, "OK\t", 3) == 0);
                        line = t_strconcat("FAIL\t",
index d9de051e81649ee4ea965f44db1eab0662a502ac..0f2b3c83629a831c7e0b1c613c8d4ca32e9d1774 100644 (file)
@@ -10,6 +10,7 @@
 #include "auth-connection.h"
 #include "doveadm-connection.h"
 #include "login-connection.h"
+#include "notify-connection.h"
 #include "director.h"
 #include "director-host.h"
 #include "director-connection.h"
@@ -21,6 +22,7 @@
 #define AUTH_SOCKET_PATH "login/login"
 
 static struct director *director;
+static struct notify_connection *notify_conn;
 static char *auth_socket_path;
 
 static int director_client_connected(int fd, const struct ip_addr *ip)
@@ -42,6 +44,16 @@ static void client_connected(const struct master_service_connection *conn)
        struct ip_addr ip;
        unsigned int port, len;
 
+       if (conn->fifo) {
+               if (notify_conn != NULL) {
+                       i_error("Received another proxy-notify connection");
+                       (void)close(conn->fd);
+                       return;
+               }
+               notify_conn = notify_connection_init(director, conn->fd);
+               return;
+       }
+
        if (net_getpeername(conn->fd, &ip, &port) == 0 &&
            (IPADDR_IS_V4(&ip) || IPADDR_IS_V6(&ip))) {
                /* TCP/IP connection - this is another director */
@@ -140,6 +152,7 @@ static void main_init(void)
 
 static void main_deinit(void)
 {
+       notify_connection_deinit(&notify_conn);
        director_deinit(&director);
        doveadm_connections_deinit();
        login_connections_deinit();
diff --git a/src/director/notify-connection.c b/src/director/notify-connection.c
new file mode 100644 (file)
index 0000000..7de3e23
--- /dev/null
@@ -0,0 +1,62 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "istream.h"
+#include "director.h"
+#include "user-directory.h"
+#include "notify-connection.h"
+
+#include <unistd.h>
+
+struct notify_connection {
+       int fd;
+       struct io *io;
+       struct istream *input;
+       struct director *dir;
+};
+
+static void notify_connection_input(struct notify_connection *conn)
+{
+       struct user *user;
+       const char *line;
+       unsigned int hash;
+
+       while ((line = i_stream_read_next_line(conn->input)) != NULL) {
+               hash = user_directory_get_username_hash(line);
+               user = user_directory_lookup(conn->dir->users, hash);
+               if (user != NULL) {
+                       user_directory_refresh(conn->dir->users, user);
+                       director_update_user(conn->dir, conn->dir->self_host,
+                                            user);
+               }
+       }
+       if (conn->input->eof || conn->input->stream_errno != 0)
+               notify_connection_deinit(&conn);
+}
+
+struct notify_connection *
+notify_connection_init(struct director *dir, int fd)
+{
+       struct notify_connection *conn;
+
+       conn = i_new(struct notify_connection, 1);
+       conn->fd = fd;
+       conn->dir = dir;
+       conn->input = i_stream_create_fd(conn->fd, 1024, FALSE);
+       conn->io = io_add(conn->fd, IO_READ, notify_connection_input, conn);
+       return conn;
+}
+
+void notify_connection_deinit(struct notify_connection **_conn)
+{
+       struct notify_connection *conn = *_conn;
+
+       *_conn = NULL;
+
+       io_remove(&conn->io);
+       i_stream_unref(&conn->input);
+       if (close(conn->fd) < 0)
+               i_error("close(notify connection) failed: %m");
+       i_free(conn);
+}
diff --git a/src/director/notify-connection.h b/src/director/notify-connection.h
new file mode 100644 (file)
index 0000000..cb62170
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef NOTIFY_CONNECTION_H
+#define NOTIFY_CONNECTION_H
+
+struct director;
+
+struct notify_connection *notify_connection_init(struct director *dir, int fd);
+void notify_connection_deinit(struct notify_connection **conn);
+
+#endif