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,
 };