changeset 22567:c27c8ce1d534

director: After CONNECT was received, make sure we disconnect The remote side won't be reading anything after the CONNECT, so we have to disconnect anyway. If we decide that the CONNECT request is wrong, reconnect after a short delay and hope that the remote agrees with us the next time.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 14 Sep 2017 17:57:29 +0300
parents 98b21e27d66c
children c50f46578b86
files src/director/director-connection.c
diffstat 1 files changed, 35 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/director/director-connection.c	Thu Sep 14 17:48:50 2017 +0300
+++ b/src/director/director-connection.c	Thu Sep 14 17:57:29 2017 +0300
@@ -73,6 +73,7 @@
 /* If outgoing director connection exists for less than this many seconds,
    mark the host as failed so we won't try to reconnect to it immediately */
 #define DIRECTOR_SUCCESS_MIN_CONNECT_SECS 40
+#define DIRECTOR_RECONNECT_AFTER_WRONG_CONNECT_MSECS 1000
 #define DIRECTOR_WAIT_DISCONNECT_SECS 10
 #define DIRECTOR_HANDSHAKE_WARN_SECS 29
 #define DIRECTOR_HANDSHAKE_BYTES_LOG_MIN_SECS (60*30)
@@ -1592,6 +1593,31 @@
 	return TRUE;
 }
 
+static void director_disconnect_timeout(struct director_connection *conn)
+{
+	director_connection_deinit(&conn, "CONNECT requested");
+}
+
+static void
+director_reconnect_after_wrong_connect_timeout(struct director_connection *conn)
+{
+	struct director *dir = conn->dir;
+
+	director_connection_deinit(&conn, "Wrong CONNECT requested");
+	if (dir->right == NULL)
+		director_connect(dir, "Reconnecting after wrong CONNECT request");
+}
+
+static void
+director_reconnect_after_wrong_connect(struct director_connection *conn)
+{
+	if (conn->to_disconnect != NULL)
+		return;
+	conn->to_disconnect =
+		timeout_add_short(DIRECTOR_RECONNECT_AFTER_WRONG_CONNECT_MSECS,
+				  director_reconnect_after_wrong_connect_timeout, conn);
+}
+
 static bool director_cmd_connect(struct director_connection *conn,
 				 const char *const *args)
 {
@@ -1616,6 +1642,7 @@
 		/* the old connection is the correct one */
 		dir_debug("Ignoring CONNECT request to %s (current right is %s)",
 			  host->name, dir->right->name);
+		director_reconnect_after_wrong_connect(conn);
 		return TRUE;
 	}
 
@@ -1629,6 +1656,14 @@
 	} else {
 		right_state = t_strdup_printf("replacing current right %s",
 					      dir->right->name);
+		/* disconnect from right side immediately - it's not accepting
+		   any further commands from us. */
+		if (conn->dir->right != conn)
+			director_connection_deinit(&conn->dir->right, "CONNECT requested");
+		else if (conn->to_disconnect == NULL) {
+			conn->to_disconnect =
+				timeout_add_short(0, director_disconnect_timeout, conn);
+		}
 	}
 
 	/* connect here */