]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: smtp-client-connection - Restructure handling of immediate connection failure.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 14 Jul 2018 09:35:20 +0000 (11:35 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Mon, 24 Aug 2020 07:20:16 +0000 (07:20 +0000)
The delayed error callback is now started at a single location, much like
lib-http/client deals with this situation.

src/lib-smtp/smtp-client-connection.c
src/lib-smtp/smtp-client-private.h

index 297389cc12768acde4d2dcd3f5cb68b89803f46d..3f7d074b242f224a9885b507c85a60ce440972e0 100644 (file)
@@ -297,9 +297,10 @@ void smtp_client_connection_fail(struct smtp_client_connection *conn,
        struct smtp_reply reply;
        const char *text_lines[] = {error, NULL};
 
+       timeout_remove(&conn->to_connect);
+
        if (status == SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED &&
            !smtp_client_connection_last_ip(conn)) {
-               i_assert(conn->to_connect == NULL);
                conn->to_connect = timeout_add_short(
                        0, smtp_client_connection_connect_next_ip, conn);
                return;
@@ -1226,8 +1227,12 @@ static void smtp_client_connection_destroy(struct connection *_conn)
                break;
        default:
        case CONNECTION_DISCONNECT_CONN_CLOSED:
-               if (conn->connect_failed)
+               if (conn->connect_failed) {
+                       smtp_client_connection_fail(conn,
+                               SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
+                               "Failed to connect to remote server");
                        break;
+               }
                error = (_conn->input == NULL ?
                         "Connection lost" :
                         t_strdup_printf("Connection lost: %s",
@@ -1384,19 +1389,6 @@ smtp_client_connection_ssl_init(struct smtp_client_connection *conn,
        return 0;
 }
 
-static void
-smtp_client_connection_delayed_connect_failure(
-       struct smtp_client_connection *conn)
-{
-       e_debug(conn->event, "Delayed connect failure");
-
-       i_assert(conn->to_connect != NULL);
-       timeout_remove(&conn->to_connect);
-       smtp_client_connection_fail(
-               conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
-               "Failed to connect to remote server");
-}
-
 static void
 smtp_client_connection_connected(struct connection *_conn, bool success)
 {
@@ -1408,10 +1400,6 @@ smtp_client_connection_connected(struct connection *_conn, bool success)
        if (!success) {
                e_error(conn->event, "connect(%s) failed: %m", _conn->name);
                conn->connect_failed = TRUE;
-               timeout_remove(&conn->to_connect);
-               conn->to_connect = timeout_add_short(
-                       0, smtp_client_connection_delayed_connect_failure,
-                       conn);
                return;
        }
 
@@ -1450,11 +1438,9 @@ smtp_client_connection_connected(struct connection *_conn, bool success)
                if (smtp_client_connection_ssl_init(conn, &error) < 0) {
                        e_error(conn->event, "connect(%s) failed: %s",
                                _conn->name, error);
-                       timeout_remove(&conn->to_connect);
-                       conn->to_connect = timeout_add_short(
-                               0,
-                               smtp_client_connection_delayed_connect_failure,
-                               conn);
+                       smtp_client_connection_fail(
+                               conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
+                               "Failed to connect to remote server");
                }
        } else {
                smtp_client_connection_established(conn);
@@ -1496,6 +1482,19 @@ smtp_client_connection_connect_timeout(struct smtp_client_connection *conn)
        }
 }
 
+static void
+smtp_client_connection_delayed_connect_error(struct smtp_client_connection *conn)
+{
+       e_debug(conn->event, "Delayed connect error");
+
+       timeout_remove(&conn->to_connect);
+       errno = conn->connect_errno;
+       smtp_client_connection_connected(&conn->conn, FALSE);
+       smtp_client_connection_fail(conn,
+               SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
+               "Failed to connect to remote server");
+}
+
 static void
 smtp_client_connection_do_connect(struct smtp_client_connection *conn)
 {
@@ -1509,7 +1508,10 @@ smtp_client_connection_do_connect(struct smtp_client_connection *conn)
        p_clear(conn->state_pool);
 
        if (connection_client_connect(&conn->conn) < 0) {
-               smtp_client_connection_connected(&conn->conn, FALSE);
+               conn->connect_errno = errno;
+               e_debug(conn->event, "Connect failed: %m");
+               conn->to_connect = timeout_add_short(0,
+                       smtp_client_connection_delayed_connect_error, conn);
                return;
        }
 
index d0b44875db0663b1db81f249d098771c6d85be43..b0a65d344f98a524ce42a538060083b56f856852 100644 (file)
@@ -170,6 +170,8 @@ struct smtp_client_connection {
        in_port_t port;
        enum smtp_client_connection_ssl_mode ssl_mode;
 
+       int connect_errno;
+
        struct smtp_client_settings set;
        char *password;
        ARRAY_TYPE(const_string) extra_capabilities;