Mercurial > dovecot > core-2.2
changeset 16852:a8fe88d2286d
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.
author | Stephan Bosch <stephan@rename-it.nl> |
---|---|
date | Sat, 12 Oct 2013 10:57:05 +0300 |
parents | b4d54b6f3d10 |
children | 9709839d2be7 |
files | src/lib-http/http-client-connection.c src/lib-http/http-client-private.h src/lib-http/http-client-request.c src/lib-http/http-client.h |
diffstat | 4 files changed, 22 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-http/http-client-connection.c Sat Oct 12 10:55:38 2013 +0300 +++ b/src/lib-http/http-client-connection.c Sat Oct 12 10:57:05 2013 +0300 @@ -74,7 +74,8 @@ 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 @@ "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);
--- a/src/lib-http/http-client-private.h Sat Oct 12 10:55:38 2013 +0300 +++ b/src/lib-http/http-client-private.h Sat Oct 12 10:57:05 2013 +0300 @@ -232,7 +232,7 @@ 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 @@ 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,
--- a/src/lib-http/http-client-request.c Sat Oct 12 10:55:38 2013 +0300 +++ b/src/lib-http/http-client-request.c Sat Oct 12 10:57:05 2013 +0300 @@ -377,11 +377,20 @@ 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 @@ 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 @@ 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 @@ 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. */
--- a/src/lib-http/http-client.h Sat Oct 12 10:55:38 2013 +0300 +++ b/src/lib-http/http-client.h Sat Oct 12 10:57:05 2013 +0300 @@ -16,6 +16,7 @@ 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, };