From: Stephan Bosch Date: Sat, 12 Oct 2013 07:57:05 +0000 (+0300) Subject: lib-http: http-client: Added request error code for broken payload input stream. X-Git-Tag: 2.2.7~77 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=50d1446e71cfbdc5b6d7bafcf91b7bff453989d3;p=thirdparty%2Fdovecot%2Fcore.git lib-http: http-client: Added request error code for broken payload input stream. This error is triggered when reading from the provided payload input stream fails while sending the request. Previously this would yield the same error code as for a failure to write to the connection output. --- diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c index 0d20b5c670..fa0b782dd7 100644 --- a/src/lib-http/http-client-connection.c +++ b/src/lib-http/http-client-connection.c @@ -74,7 +74,8 @@ http_client_connection_retry_requests(struct http_client_connection *conn, struct http_client_request **req; array_foreach_modifiable(&conn->request_wait_list, req) { - http_client_request_retry(*req, status, error); + if ((*req)->state < HTTP_REQUEST_STATE_FINISHED) + http_client_request_retry(*req, status, error); http_client_request_unref(req); } array_clear(&conn->request_wait_list); @@ -93,7 +94,8 @@ http_client_connection_server_close(struct http_client_connection **_conn) "Server explicitly closed connection"); array_foreach_modifiable(&conn->request_wait_list, req) { - http_client_request_resubmit(*req); + if ((*req)->state < HTTP_REQUEST_STATE_FINISHED) + http_client_request_resubmit(*req); http_client_request_unref(req); } array_clear(&conn->request_wait_list); diff --git a/src/lib-http/http-client-private.h b/src/lib-http/http-client-private.h index ddf554991f..d17a156a3d 100644 --- a/src/lib-http/http-client-private.h +++ b/src/lib-http/http-client-private.h @@ -232,7 +232,7 @@ int http_client_init_ssl_ctx(struct http_client *client, const char **error_r); void http_client_request_ref(struct http_client_request *req); void http_client_request_unref(struct http_client_request **_req); int http_client_request_send(struct http_client_request *req, - const char **error_r); + const char **error_r); int http_client_request_send_more(struct http_client_request *req, const char **error_r); bool http_client_request_callback(struct http_client_request *req, @@ -242,6 +242,8 @@ void http_client_request_retry(struct http_client_request *req, unsigned int status, const char *error); void http_client_request_retry_response(struct http_client_request *req, struct http_response *response); +void http_client_request_send_error(struct http_client_request *req, + unsigned int status, const char *error); void http_client_request_error(struct http_client_request *req, unsigned int status, const char *error); void http_client_request_redirect(struct http_client_request *req, diff --git a/src/lib-http/http-client-request.c b/src/lib-http/http-client-request.c index bd23a2c4d8..c16574a32a 100644 --- a/src/lib-http/http-client-request.c +++ b/src/lib-http/http-client-request.c @@ -377,11 +377,20 @@ int http_client_request_send_more(struct http_client_request *req, o_stream_set_max_buffer_size(output, (size_t)-1); if (req->payload_input->stream_errno != 0) { + /* the payload stream assigned to this request is broken, + fail this the request immediately */ + http_client_request_send_error(req, + HTTP_CLIENT_REQUEST_ERROR_BROKEN_PAYLOAD, + "Broken payload stream"); + + /* we're in the middle of sending a request, so the connection + will also have to be aborted */ errno = req->payload_input->stream_errno; *error_r = t_strdup_printf("read(%s) failed: %m", i_stream_get_name(req->payload_input)); ret = -1; } else if (output->stream_errno != 0) { + /* failed to send request */ errno = output->stream_errno; *error_r = t_strdup_printf("write(%s) failed: %m", o_stream_get_name(output)); @@ -393,6 +402,7 @@ int http_client_request_send_more(struct http_client_request *req, if (ret < 0 || i_stream_is_eof(req->payload_input)) { if (!req->payload_chunked && req->payload_input->v_offset - req->payload_offset != req->payload_size) { + *error_r = "stream input size changed [BUG]"; i_error("stream input size changed"); //FIXME return -1; } @@ -552,12 +562,14 @@ bool http_client_request_callback(struct http_client_request *req, return TRUE; } -static void +void http_client_request_send_error(struct http_client_request *req, unsigned int status, const char *error) { http_client_request_callback_t *callback; + if (req->state >= HTTP_REQUEST_STATE_FINISHED) + return; req->state = HTTP_REQUEST_STATE_ABORTED; callback = req->callback; @@ -603,7 +615,7 @@ static void http_client_request_error_delayed(struct http_client_request *req) void http_client_request_error(struct http_client_request *req, unsigned int status, const char *error) { - if (!req->submitted) { + if (!req->submitted && req->state < HTTP_REQUEST_STATE_FINISHED) { /* we're still in http_client_request_submit(). delay reporting the error, so the caller doesn't have to handle immediate callbacks. */ diff --git a/src/lib-http/http-client.h b/src/lib-http/http-client.h index 9cd36e10f2..cfd3f0b10a 100644 --- a/src/lib-http/http-client.h +++ b/src/lib-http/http-client.h @@ -16,6 +16,7 @@ enum http_client_request_error { HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT, HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST, + HTTP_CLIENT_REQUEST_ERROR_BROKEN_PAYLOAD, HTTP_CLIENT_REQUEST_ERROR_BAD_RESPONSE, HTTP_CLIENT_REQUEST_ERROR_TIMED_OUT, };