]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: http-client: Added request error code for broken payload input stream.
authorStephan Bosch <stephan@rename-it.nl>
Sat, 12 Oct 2013 07:57:05 +0000 (10:57 +0300)
committerStephan Bosch <stephan@rename-it.nl>
Sat, 12 Oct 2013 07:57:05 +0000 (10:57 +0300)
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.

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

index 0d20b5c6707e51269b131dba62c656626b54a0f2..fa0b782dd700fa5758f02d42937a9bceb98cb6e4 100644 (file)
@@ -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);
index ddf554991f2c97e7d37b9bd546bd926fb01dda77..d17a156a3d9dfe6deed978beb7eaacd92f9c3790 100644 (file)
@@ -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,
index bd23a2c4d8c6088e4664ffb4628d50a5277e6afd..c16574a32aea84b5a3ccabb99f37ecfbb3a04b52 100644 (file)
@@ -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. */
index 9cd36e10f21bf15ef9ec303f2aac571027170eef..cfd3f0b10ada84ab1f81f25c7744cdd209a4f406 100644 (file)
@@ -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,
 };