]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: Pass connect failures all the way to request callback's error string.
authorTimo Sirainen <tss@iki.fi>
Thu, 4 Apr 2013 11:58:00 +0000 (14:58 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 4 Apr 2013 11:58:00 +0000 (14:58 +0300)
src/lib-http/http-client-connection.c
src/lib-http/http-client-host.c
src/lib-http/http-client-peer.c
src/lib-http/http-client-private.h

index f7e87eae31a3f1a2ae02ee6ade2cff389d6fefcc..bf357ad7d7b9bb36a9911ffd158d9146e99c4d1c 100644 (file)
@@ -307,7 +307,8 @@ static void http_client_connection_destroy(struct connection *_conn)
 
        switch (_conn->disconnect_reason) {
        case CONNECTION_DISCONNECT_CONNECT_TIMEOUT:
-               http_client_peer_connection_failure(conn->peer);
+               http_client_peer_connection_failure(conn->peer, t_strdup_printf(
+                       "connect(%s) failed: Connection timed out", _conn->name));
                break;
        case CONNECTION_DISCONNECT_CONN_CLOSED:
                /* retry pending requests if possible */
@@ -683,15 +684,13 @@ static int http_client_connection_ssl_handshaked(void *context)
 }
 
 static int 
-http_client_connection_ssl_init(struct http_client_connection *conn)
+http_client_connection_ssl_init(struct http_client_connection *conn,
+                               const char **error_r)
 {
        struct ssl_iostream_settings ssl_set;
        const char *source, *error;
 
-       if (conn->client->ssl_ctx == NULL) {
-               http_client_connection_error(conn, "No SSL context");
-               return -1;
-       }
+       i_assert(conn->client->ssl_ctx != NULL);
 
        memset(&ssl_set, 0, sizeof(ssl_set));
        if (conn->client->set.ssl_verify) {
@@ -708,15 +707,16 @@ http_client_connection_ssl_init(struct http_client_connection *conn)
        if (io_stream_create_ssl(conn->client->ssl_ctx, source, &ssl_set,
                                 &conn->conn.input, &conn->conn.output,
                                 &conn->ssl_iostream, &error) < 0) {
-               http_client_connection_error(conn,
-                       "Couldn't initialize SSL client: %s", error);
+               *error_r = t_strdup_printf(
+                       "Couldn't initialize SSL client for %s: %s",
+                       conn->conn.name, error);
                return -1;
        }
        ssl_iostream_set_handshake_callback(conn->ssl_iostream,
                                            http_client_connection_ssl_handshaked, conn);
        if (ssl_iostream_handshake(conn->ssl_iostream) < 0) {
-               http_client_connection_error(conn, "SSL handshake failed: %s",
-                       ssl_iostream_get_last_error(conn->ssl_iostream));
+               *error_r = t_strdup_printf("SSL handshake to %s failed: %s",
+                       conn->conn.name, ssl_iostream_get_last_error(conn->ssl_iostream));
                return -1;
        }
 
@@ -729,16 +729,16 @@ http_client_connection_connected(struct connection *_conn, bool success)
 {
        struct http_client_connection *conn =
                (struct http_client_connection *)_conn;
+       const char *error;
 
        if (!success) {
-               http_client_connection_error(conn, "connect(%s) failed: %m",
-                                            _conn->name);
-               http_client_peer_connection_failure(conn->peer);
+               http_client_peer_connection_failure(conn->peer, t_strdup_printf(
+                       "connect(%s) failed: %m", _conn->name));
        } else {
                http_client_connection_debug(conn, "Connected");
                if (conn->peer->addr.ssl) {
-                       if (http_client_connection_ssl_init(conn) < 0) {
-                               http_client_peer_connection_failure(conn->peer);
+                       if (http_client_connection_ssl_init(conn, &error) < 0) {
+                               http_client_peer_connection_failure(conn->peer, error);
                                http_client_connection_unref(&conn);
                        }
                        return;
index a4899e4e02f7735b0bffe9b2a9d8d66ea68004ee..61c896f3cf5b7bfdb7a144df8b1fca7f7ea9d705 100644 (file)
@@ -119,17 +119,6 @@ http_client_host_connection_setup(struct http_client_host *host,
        struct http_client_peer *peer = NULL;
        struct http_client_peer_addr addr;
 
-       if (hport->ips_connect_idx == host->ips_count) {
-               /* all IPs failed, but retry all of them again on the
-                  next request. */
-               hport->ips_connect_idx = 0;
-               http_client_host_port_error
-                       (hport, HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, "Connection failed");
-               if (host->client->ioloop != NULL)
-                       io_loop_stop(host->client->ioloop);
-               return;
-       }
-
        addr.ip = host->ips[hport->ips_connect_idx];
        addr.port = hport->port;
        addr.ssl = hport->ssl;
@@ -142,18 +131,28 @@ http_client_host_connection_setup(struct http_client_host *host,
 }
 
 void http_client_host_connection_failure(struct http_client_host *host,
-       const struct http_client_peer_addr *addr)
+       const struct http_client_peer_addr *addr, const char *reason)
 {
        struct http_client_host_port *hport;
 
-       http_client_host_debug(host, "Failed to connect to %s:%u", 
-               net_ip2addr(&addr->ip), addr->port);
+       http_client_host_debug(host, "Failed to connect to %s:%u: %s",
+               net_ip2addr(&addr->ip), addr->port, reason);
 
        hport = http_client_host_port_find(host, addr->port, addr->ssl);
        if (hport == NULL)
                return;
 
-       hport->ips_connect_idx++;
+       i_assert(hport->ips_connect_idx < host->ips_count);
+       if (++hport->ips_connect_idx == host->ips_count) {
+               /* all IPs failed, but retry all of them again on the
+                  next request. */
+               hport->ips_connect_idx = 0;
+               http_client_host_port_error(hport,
+                       HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, reason);
+               if (host->client->ioloop != NULL)
+                       io_loop_stop(host->client->ioloop);
+               return;
+       }
        http_client_host_connection_setup(host, hport);
 }
 
@@ -302,6 +301,7 @@ void http_client_host_submit_request(struct http_client_host *host,
        /* make a connection if we have an IP already */
        if (host->ips_count == 0)
                return;
+       i_assert(hport->ips_connect_idx == 0);
        http_client_host_connection_setup(host, hport);
 }
 
index 8cb328a2ecabc47da7308cc6cddfff133f95376a..fc95348b3a2749ee43042b5a266201d76d723b6d 100644 (file)
@@ -279,7 +279,8 @@ http_client_peer_claim_request(struct http_client_peer *peer, bool no_urgent)
        return NULL;
 }
 
-void http_client_peer_connection_failure(struct http_client_peer *peer)
+void http_client_peer_connection_failure(struct http_client_peer *peer,
+                                        const char *reason)
 {
        struct http_client_host *const *host;
        unsigned int num_urgent;
@@ -299,7 +300,7 @@ void http_client_peer_connection_failure(struct http_client_peer *peer)
                   failed. a second connect will probably also fail, so just
                   abort all requests. */
                array_foreach(&peer->hosts, host) {
-                       http_client_host_connection_failure(*host, &peer->addr);
+                       http_client_host_connection_failure(*host, &peer->addr, reason);
                }
        }
        if (array_count(&peer->conns) == 0 &&
index b6ed299d968bfbcd6b42b8c8f39af3089603f29e..1dc54c327af992e0e7708cb9883bae8b85f6342f 100644 (file)
@@ -232,7 +232,8 @@ struct http_client_request *
        http_client_peer_claim_request(struct http_client_peer *peer,
                bool no_urgent);
 void http_client_peer_handle_requests(struct http_client_peer *peer);
-void http_client_peer_connection_failure(struct http_client_peer *peer);
+void http_client_peer_connection_failure(struct http_client_peer *peer,
+                                        const char *reason);
 void http_client_peer_connection_lost(struct http_client_peer *peer);
 unsigned int http_client_peer_idle_connections(struct http_client_peer *peer);
 
@@ -245,7 +246,7 @@ struct http_client_request *
 http_client_host_claim_request(struct http_client_host *host,
        const struct http_client_peer_addr *addr, bool no_urgent);
 void http_client_host_connection_failure(struct http_client_host *host,
-       const struct http_client_peer_addr *addr);
+       const struct http_client_peer_addr *addr, const char *reason);
 unsigned int http_client_host_requests_pending(struct http_client_host *host,
        const struct http_client_peer_addr *addr, unsigned int *num_urgent_r);
 void http_client_host_drop_request(struct http_client_host *host,