dovecot-2.0: director: Handle CONNECT commands (properly).

dovecot at dovecot.org dovecot at dovecot.org
Thu Jun 17 21:16:13 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/75d5e31ea8cc
changeset: 11571:75d5e31ea8cc
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Jun 17 19:16:09 2010 +0100
description:
director: Handle CONNECT commands (properly).

diffstat:

 src/director/director-connection.c |  44 ++++++++++++++++++++++++++++++++++++++++++--
 src/director/director-host.c       |  19 +++++++++++++++----
 src/director/director-host.h       |   6 ++++--
 3 files changed, 61 insertions(+), 8 deletions(-)

diffs (120 lines):

diff -r 870cd20ada71 -r 75d5e31ea8cc src/director/director-connection.c
--- a/src/director/director-connection.c	Thu Jun 17 19:12:23 2010 +0100
+++ b/src/director/director-connection.c	Thu Jun 17 19:16:09 2010 +0100
@@ -114,7 +114,7 @@
 		director_connection_deinit(&dir->left);
 	} else {
 		if (director_host_cmp_to_self(dir->left->host, host,
-					      dir->self_host) > 0) {
+					      dir->self_host) < 0) {
 			/* the old connection is the correct one.
 			   refer the client there. */
 			director_connection_send(conn, t_strdup_printf(
@@ -505,6 +505,43 @@
 	return TRUE;
 }
 
+static bool director_cmd_connect(struct director_connection *conn,
+				 const char *const *args)
+{
+	struct director *dir = conn->dir;
+	struct director_host *host;
+	struct ip_addr ip;
+	unsigned int port;
+
+	if (str_array_length(args) != 2 ||
+	    director_args_parse_ip_port(conn, args, &ip, &port) < 0) {
+		i_error("director(%s): Invalid CONNECT args", conn->name);
+		return FALSE;
+	}
+
+	host = director_host_lookup(dir, &ip, port);
+	if (host == NULL) {
+		i_error("Received CONNECT request to unknown host %s:%u",
+			net_ip2addr(&ip), port);
+		return TRUE;
+	}
+
+	/* remote suggests us to connect elsewhere */
+	if (dir->right != NULL &&
+	    director_host_cmp_to_self(host, dir->right->host,
+				      dir->self_host) <= 0) {
+		/* the old connection is the correct one */
+		return TRUE;
+	}
+
+	/* connect here, disconnect old one */
+	if (dir->right != NULL)
+		director_connection_deinit(&dir->right);
+
+	(void)director_connect_host(dir, host);
+	return TRUE;
+}
+
 static bool
 director_connection_handle_line(struct director_connection *conn,
 				const char *line)
@@ -521,7 +558,8 @@
 		if (!director_connection_handle_handshake(conn, cmd, args)) {
 			/* invalid commands during handshake,
 			   we probably don't want to reconnect here */
-			conn->host->last_failed = ioloop_time;
+			if (conn->host != NULL)
+				conn->host->last_failed = ioloop_time;
 			return FALSE;
 		}
 		return TRUE;
@@ -539,6 +577,8 @@
 		return director_cmd_director(conn, args);
 	if (strcmp(cmd, "SYNC") == 0)
 		return director_connection_sync(conn, args, line);
+	if (strcmp(cmd, "CONNECT") == 0)
+		return director_cmd_connect(conn, args);
 
 	if (strcmp(cmd, "PING") == 0) {
 		director_connection_send(conn, "PONG\n");
diff -r 870cd20ada71 -r 75d5e31ea8cc src/director/director-host.c
--- a/src/director/director-host.c	Thu Jun 17 19:12:23 2010 +0100
+++ b/src/director/director-host.c	Thu Jun 17 19:16:09 2010 +0100
@@ -89,10 +89,21 @@
 			      const struct director_host *b2,
 			      const struct director_host *self)
 {
-	if (director_host_cmp(b1, self) < 0)
-		return director_host_cmp(b1, b2);
-	else
-		return director_host_cmp(b2, b1);
+	int ret;
+
+	if ((ret = director_host_cmp(b1, b2)) >= 0)
+		return ret == 0 ? 0 : -director_host_cmp_to_self(b2, b1, self);
+
+	/* order -> return:
+	   self, b1, b2 -> b2
+	   b1, self, b2 -> b1
+	   b1, b2, self -> b2
+	*/
+	if (director_host_cmp(self, b1) < 0)
+		return 1; /* self, b1, b2 */
+	if (director_host_cmp(self, b2) < 0)
+		return -1; /* b1, self, b2 */
+	return 1; /* b1, b2, self */
 }
 
 static void director_host_add_string(struct director *dir, const char *host)
diff -r 870cd20ada71 -r 75d5e31ea8cc src/director/director-host.h
--- a/src/director/director-host.h	Thu Jun 17 19:12:23 2010 +0100
+++ b/src/director/director-host.h	Thu Jun 17 19:16:09 2010 +0100
@@ -38,8 +38,10 @@
 struct director_host *
 director_host_lookup_ip(struct director *dir, const struct ip_addr *ip);
 
-/* Returns -1 if b1 is more on our left side than b2, 1 if b2 is,
-   0 if they equal. */
+/* Returns 0 if b1 equals b2.
+   -1 if b1 is closer to our left side than b2 or
+   -1 if b2 is closer to our right side than b1
+   1 vice versa */
 int director_host_cmp_to_self(const struct director_host *b1,
 			      const struct director_host *b2,
 			      const struct director_host *self);


More information about the dovecot-cvs mailing list