Mercurial > dovecot > core-2.2
changeset 11571:75d5e31ea8cc HEAD
director: Handle CONNECT commands (properly).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 17 Jun 2010 19:16:09 +0100 |
parents | 870cd20ada71 |
children | 659bb1a26da4 |
files | src/director/director-connection.c src/director/director-host.c src/director/director-host.h |
diffstat | 3 files changed, 61 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- 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");
--- 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)
--- 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);