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