From: Stephan Bosch Date: Fri, 16 Dec 2016 22:36:19 +0000 (+0100) Subject: lib-http: client: Treat connections that get disconnected prematurely as connection... X-Git-Tag: 2.3.0.rc1~2399 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f17ac27e5989d6b3b3e4f4fb249bef4b06833ab7;p=thirdparty%2Fdovecot%2Fcore.git 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 --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c index b6d39f7ee8..11222cfd5c 100644 --- a/src/lib-http/http-client-connection.c +++ b/src/lib-http/http-client-connection.c @@ -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) diff --git a/src/lib-http/http-client-peer.c b/src/lib-http/http-client-peer.c index 3813bb5a1b..b0d2492108 100644 --- a/src/lib-http/http-client-peer.c +++ b/src/lib-http/http-client-peer.c @@ -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, diff --git a/src/lib-http/http-client-private.h b/src/lib-http/http-client-private.h index fa4a2f8a1e..c25c3a0a3d 100644 --- a/src/lib-http/http-client-private.h +++ b/src/lib-http/http-client-private.h @@ -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);