# HG changeset patch # User Stephan Bosch # Date 1481927779 -3600 # Node ID 919df3038bf50fd01511a8676207398a515a42fc # Parent f7bc77720fe59ece61053f786b7035a0ac15f667 lib-http: client: Treat connections that get disconnected prematurely as connection failures. 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. diff -r f7bc77720fe5 -r 919df3038bf5 src/lib-http/http-client-connection.c --- a/src/lib-http/http-client-connection.c Fri Dec 16 22:30:42 2016 +0100 +++ b/src/lib-http/http-client-connection.c Fri Dec 16 23:36:19 2016 +0100 @@ -298,6 +298,9 @@ } } + 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); } @@ -1546,7 +1549,7 @@ } 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) diff -r f7bc77720fe5 -r 919df3038bf5 src/lib-http/http-client-peer.c --- a/src/lib-http/http-client-peer.c Fri Dec 16 22:30:42 2016 +0100 +++ b/src/lib-http/http-client-peer.c Fri Dec 16 23:36:19 2016 +0100 @@ -813,7 +813,8 @@ } } -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 @@ 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, diff -r f7bc77720fe5 -r 919df3038bf5 src/lib-http/http-client-private.h --- a/src/lib-http/http-client-private.h Fri Dec 16 22:30:42 2016 +0100 +++ b/src/lib-http/http-client-private.h Fri Dec 16 23:36:19 2016 +0100 @@ -178,6 +178,7 @@ unsigned int connect_initialized:1; /* connection was initialized */ unsigned int connect_succeeded:1; /* connection succeeded including SSL */ unsigned int connect_failed:1; /* connection failed */ + unsigned int lost_prematurely:1; /* lost connection before receiving any data */ unsigned int closing:1; unsigned int disconnected:1; unsigned int close_indicated:1; @@ -465,7 +466,8 @@ 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);