From: Timo Sirainen Date: Wed, 19 May 2010 10:23:32 +0000 (+0200) Subject: director: Tell login proxy to notify director of open connections every director_user... X-Git-Tag: 2.0.beta6~205 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=300e4e43ed1ca46d0614459161ca2fb460ef661a;p=thirdparty%2Fdovecot%2Fcore.git director: Tell login proxy to notify director of open connections every director_user_expire/2 secs. --HG-- branch : HEAD --- diff --git a/doc/example-config/conf.d/10-director.conf b/doc/example-config/conf.d/10-director.conf index 0361c8559c..dceaa46a64 100644 --- a/doc/example-config/conf.d/10-director.conf +++ b/doc/example-config/conf.d/10-director.conf @@ -11,21 +11,24 @@ # 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 = } diff --git a/src/director/Makefile.am b/src/director/Makefile.am index eee9f977fc..9ac2b04d50 100644 --- a/src/director/Makefile.am +++ b/src/director/Makefile.am @@ -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 diff --git a/src/director/director-settings.c b/src/director/director-settings.c index 37d3d5f0a8..3af1ef6ccf 100644 --- a/src/director/director-settings.c +++ b/src/director/director-settings.c @@ -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, } +}; /* */ 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 diff --git a/src/director/login-connection.c b/src/director/login-connection.c index 4c3f1ad3dc..43a7825139 100644 --- a/src/director/login-connection.c +++ b/src/director/login-connection.c @@ -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", diff --git a/src/director/main.c b/src/director/main.c index d9de051e81..0f2b3c8362 100644 --- a/src/director/main.c +++ b/src/director/main.c @@ -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(¬ify_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 index 0000000000..7de3e233fc --- /dev/null +++ b/src/director/notify-connection.c @@ -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 + +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 index 0000000000..cb6217015e --- /dev/null +++ b/src/director/notify-connection.h @@ -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