]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: client: Treat connections that get disconnected prematurely as connection...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Fri, 16 Dec 2016 22:36:19 +0000 (23:36 +0100)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 17 Dec 2016 18:44:38 +0000 (19:44 +0100)
This means that the backoff time is increased when this happens.
A premature disconnection happens when the connection is disconnected before any data is received from the server.

src/lib-http/http-client-connection.c
src/lib-http/http-client-peer.c
src/lib-http/http-client-private.h

index b6d39f7ee869273ed2d43574853b524212c48d70..11222cfd5cfd296db277728901ed461044c0d2f3 100644 (file)
@@ -298,6 +298,9 @@ http_client_connection_lost(struct http_client_connection **_conn,
                }
        }
 
+       conn->lost_prematurely = (conn->conn.input != NULL &&
+               conn->conn.input->v_offset == 0 &&
+               i_stream_get_data_size(conn->conn.input) == 0);
        http_client_connection_abort_temp_error(_conn,
                HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST, error);
 }
@@ -1545,7 +1548,7 @@ http_client_connection_disconnect(struct http_client_connection *conn)
        }
 
        if (conn->connect_succeeded)
-               http_client_peer_connection_lost(peer);
+               http_client_peer_connection_lost(peer, conn->lost_prematurely);
 }
 
 bool http_client_connection_unref(struct http_client_connection **_conn)
index 3813bb5a1bd040de6c2c2820c8060f8367000aa7..b0d2492108da86080077e4febcb8d85b10c49bad 100644 (file)
@@ -813,7 +813,8 @@ void http_client_peer_connection_failure(struct http_client_peer *peer,
        }
 }
 
-void http_client_peer_connection_lost(struct http_client_peer *peer)
+void http_client_peer_connection_lost(struct http_client_peer *peer,
+       bool premature)
 {
        unsigned int num_pending, num_urgent;
 
@@ -827,11 +828,21 @@ void http_client_peer_connection_lost(struct http_client_peer *peer)
        num_pending = http_client_peer_requests_pending(peer, &num_urgent);
 
        http_client_peer_debug(peer,
-               "Lost a connection (%u queues linked, %u connections left, "
+               "Lost a connection%s (%u queues linked, %u connections left, "
                        "%u requests pending, %u requests urgent)",
+               (premature ? " prematurely" : ""),
                array_count(&peer->queues), array_count(&peer->conns),
                num_pending, num_urgent);
 
+       /* update backoff timer if the connection was lost prematurely.
+          this prevents reconnecting immediately to a server that is
+          misbehaving by disconnecting before sending a response.
+        */
+       if (premature) {
+               peer->last_failure = ioloop_timeval;
+               http_client_peer_increase_backoff_timer(peer);
+       }
+
        if (peer->handling_requests) {
                /* we got here from the request handler loop */
                http_client_peer_debug(peer,
index fa4a2f8a1e1b5c79f117bbdcf9416277c5f2b6b2..c25c3a0a3d053177136d4af758f3334013bf7238 100644 (file)
@@ -178,6 +178,7 @@ struct http_client_connection {
        bool connect_initialized:1; /* connection was initialized */
        bool connect_succeeded:1;   /* connection succeeded including SSL */
        bool connect_failed:1;      /* connection failed */
+       bool lost_prematurely:1;    /* lost connection before receiving any data */
        bool closing:1;
        bool disconnected:1;
        bool close_indicated:1;
@@ -465,7 +466,8 @@ void http_client_peer_trigger_request_handler(struct http_client_peer *peer);
 void http_client_peer_connection_success(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);
+void http_client_peer_connection_lost(struct http_client_peer *peer,
+       bool premature);
 bool http_client_peer_is_connected(struct http_client_peer *peer);
 unsigned int
 http_client_peer_idle_connections(struct http_client_peer *peer);