dovecot-2.2: lib-http: If we get disconnected, say exactly what ...

dovecot at dovecot.org dovecot at dovecot.org
Tue Mar 5 14:32:14 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/f89ebdc1625d
changeset: 15999:f89ebdc1625d
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Mar 05 14:32:03 2013 +0200
description:
lib-http: If we get disconnected, say exactly what the error was.

diffstat:

 src/lib-http/http-client-connection.c |  41 +++++++++++++++++++++-------------
 src/lib-http/http-client-private.h    |   6 +++-
 src/lib-http/http-client-request.c    |  33 +++++++++++++++++++++------
 3 files changed, 54 insertions(+), 26 deletions(-)

diffs (220 lines):

diff -r 194ec0e10f3a -r f89ebdc1625d src/lib-http/http-client-connection.c
--- a/src/lib-http/http-client-connection.c	Tue Mar 05 14:31:43 2013 +0200
+++ b/src/lib-http/http-client-connection.c	Tue Mar 05 14:32:03 2013 +0200
@@ -200,6 +200,7 @@
 {
 	struct http_client_request *const *req_idx;
 	struct http_client_request *req;
+	const char *error;
 
 	if (conn->to_response != NULL)
 		timeout_remove(&conn->to_response);
@@ -212,18 +213,19 @@
 	req = req_idx[0];
 
 	conn->payload_continue = TRUE;
-	if (http_client_request_send_more(req) < 0) {
+	if (http_client_request_send_more(req, &error) < 0) {
 		http_client_connection_abort_temp_error(&conn,
-			HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST, "Failed to send request");
+			HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
+			t_strdup_printf("Failed to send request: %s", error));
 	}
 }
 
 bool http_client_connection_next_request(struct http_client_connection *conn)
 {
 	struct http_client_request *req = NULL;
+	const char *error;
 
 	if (!http_client_connection_is_ready(conn)) {
-		
 		http_client_connection_debug(conn, "Not ready for next request");
 		return FALSE;
 	}
@@ -250,10 +252,10 @@
 	http_client_connection_debug(conn, "Claimed request %s",
 		http_client_request_label(req));
 
-	if (http_client_request_send(req) < 0) {
+	if (http_client_request_send(req, &error) < 0) {
 		http_client_connection_abort_temp_error(&conn,
 			HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
-			"Failed to send request");
+			t_strdup_printf("Failed to send request: %s", error));
 		return FALSE;
 	}
 
@@ -292,8 +294,10 @@
 		break;
 	case CONNECTION_DISCONNECT_CONN_CLOSED:
 		/* retry pending requests if possible */
+		errno = _conn->input->stream_errno;
 		http_client_connection_retry_requests(conn,
-			HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST, "Connection lost");
+			HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
+			t_strdup_printf("Connection lost: %m"));
 	default:
 		break;
 	}
@@ -459,10 +463,10 @@
 			conn->payload_continue = TRUE;
 			http_client_connection_debug(conn,
 				"Got expected 100-continue response");
-			if (http_client_request_send_more(req) < 0) {
+			if (http_client_request_send_more(req, &error) < 0) {
 				http_client_connection_abort_temp_error(&conn,
 					HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
-					"Failed to send request");
+					t_strdup_printf("Failed to send request: %s", error));
 			}
 			return;
 		} else if (response->status / 100 == 1) {
@@ -523,13 +527,14 @@
 	}
 
 	if (ret <= 0 &&
-		(conn->conn.input->eof || conn->conn.input->stream_errno != 0)) {
+	    (conn->conn.input->eof || conn->conn.input->stream_errno != 0)) {
 		int stream_errno = conn->conn.input->stream_errno;
-		http_client_connection_debug(conn,
-			"Lost connection to server (error=%s)",
-			stream_errno != 0 ? strerror(stream_errno) : "EOF");
 		http_client_connection_abort_temp_error(&conn,
-			HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST, "Connection lost");
+			HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
+			t_strdup_printf("Connection lost: read(%s) failed: %s",
+					i_stream_get_name(conn->conn.input),
+					stream_errno != 0 ?
+					strerror(stream_errno) : "EOF"));
 		return;
 	}
 
@@ -550,12 +555,15 @@
 {
 	struct http_client_request *const *req_idx, *req;
 	struct ostream *output = conn->conn.output;
+	const char *error;
 	int ret;
 
 	if ((ret = o_stream_flush(output)) <= 0) {
 		if (ret < 0) {
 			http_client_connection_abort_temp_error(&conn,
-				HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST, "Connection lost");
+				HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
+				t_strdup_printf("Connection lost: write(%s) failed: %m",
+						o_stream_get_name(output)));
 		}
 		return ret;
 	}
@@ -565,9 +573,10 @@
 		req = req_idx[0];
 
 		if (!req->payload_sync || conn->payload_continue) {
-			if (http_client_request_send_more(req) < 0) {
+			if (http_client_request_send_more(req, &error) < 0) {
 				http_client_connection_abort_temp_error(&conn,
-					HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST, "Connection lost");
+					HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
+					t_strdup_printf("Connection lost: %s", error));
 				return -1;
 			}
 			if (!conn->output_locked) {
diff -r 194ec0e10f3a -r f89ebdc1625d src/lib-http/http-client-private.h
--- a/src/lib-http/http-client-private.h	Tue Mar 05 14:31:43 2013 +0200
+++ b/src/lib-http/http-client-private.h	Tue Mar 05 14:32:03 2013 +0200
@@ -200,8 +200,10 @@
 
 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);
-int http_client_request_send_more(struct http_client_request *req);
+int http_client_request_send(struct http_client_request *req,
+			     const char **error_r);
+int http_client_request_send_more(struct http_client_request *req,
+				  const char **error_r);
 void http_client_request_callback(struct http_client_request *req,
 	struct http_response *response);
 void http_client_request_resubmit(struct http_client_request *req);
diff -r 194ec0e10f3a -r f89ebdc1625d src/lib-http/http-client-request.c
--- a/src/lib-http/http-client-request.c	Tue Mar 05 14:31:43 2013 +0200
+++ b/src/lib-http/http-client-request.c	Tue Mar 05 14:32:03 2013 +0200
@@ -215,6 +215,7 @@
 			http_client_request_finish_payload_out(req);
 	} else { 
 		req->payload_input = i_stream_create_from_data(data, size);
+		i_stream_set_name(req->payload_input, "<HTTP request payload>");
 	}
 	req->payload_size = 0;
 	req->payload_chunked = TRUE;
@@ -275,20 +276,32 @@
 	return http_client_request_continue_payload(_req, NULL, 0);
 }
 
-int http_client_request_send_more(struct http_client_request *req)
+int http_client_request_send_more(struct http_client_request *req,
+				  const char **error_r)
 {
 	struct http_client_connection *conn = req->conn;
 	struct ostream *output = req->payload_output;
-	int ret = 0;
+	off_t ret;
 
 	i_assert(req->payload_input != NULL);
 
 	/* chunked ostream needs to write to the parent stream's buffer */
 	o_stream_set_max_buffer_size(output, IO_BLOCK_SIZE);
-	if (o_stream_send_istream(output, req->payload_input) < 0)
-		ret = -1;
+	ret = o_stream_send_istream(output, req->payload_input);
 	o_stream_set_max_buffer_size(output, (size_t)-1);
 
+	if (req->payload_input->stream_errno != 0) {
+		errno = req->payload_input->stream_errno;
+		*error_r = t_strdup_printf("read(%s) failed: %m",
+					   i_stream_get_name(req->payload_input));
+	} else if (output->stream_errno != 0) {
+		errno = output->stream_errno;
+		*error_r = t_strdup_printf("write(%s) failed: %m",
+					   o_stream_get_name(output));
+	} else {
+		i_assert(ret >= 0);
+	}
+
 	if (!i_stream_have_bytes_left(req->payload_input)) {
 		if (!req->payload_chunked &&
 			req->payload_input->v_offset - req->payload_offset != req->payload_size) {
@@ -309,10 +322,11 @@
 		o_stream_set_flush_pending(output, TRUE);
 		http_client_request_debug(req, "Partially sent payload");
 	}
-	return ret;
+	return ret < 0 ? -1 : 0;
 }
 
-int http_client_request_send(struct http_client_request *req)
+int http_client_request_send(struct http_client_request *req,
+			     const char **error_r)
 {
 	struct http_client_connection *conn = req->conn;
 	struct ostream *output = conn->conn.output;
@@ -356,14 +370,17 @@
 
 	req->state = HTTP_REQUEST_STATE_PAYLOAD_OUT;
 	o_stream_cork(output);
-	if (o_stream_sendv(output, iov, N_ELEMENTS(iov)) < 0)
+	if (o_stream_sendv(output, iov, N_ELEMENTS(iov)) < 0) {
+		*error_r = t_strdup_printf("write(%s) failed: %m",
+					   o_stream_get_name(output));
 		ret = -1;
+	}
 
 	http_client_request_debug(req, "Sent header");
 
 	if (ret >= 0 && req->payload_output != NULL) {
 		if (!req->payload_sync) {
-			if (http_client_request_send_more(req) < 0)
+			if (http_client_request_send_more(req, error_r) < 0)
 				ret = -1;
 		} else {
 			http_client_request_debug(req, "Waiting for 100-continue");


More information about the dovecot-cvs mailing list