]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
director: After CONNECT was received, make sure we disconnect
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 14 Sep 2017 14:57:29 +0000 (17:57 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 15 Sep 2017 09:00:36 +0000 (12:00 +0300)
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.

src/director/director-connection.c

index cfbe5dff3a34b023f50b805e5b2f6bd3bcaf4721..04b2a506d5649d6a26c922e1d56c6a1f3db1a931 100644 (file)
@@ -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)
@@ -1594,6 +1595,31 @@ static bool director_connection_sync(struct director_connection *conn,
        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)
 {
@@ -1618,6 +1644,7 @@ static bool director_cmd_connect(struct director_connection *conn,
                /* 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;
        }
 
@@ -1631,6 +1658,14 @@ static bool director_cmd_connect(struct director_connection *conn,
        } 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 */