changeset 19727:8f72e4f0ed5d

lib-http: client: Fixed pipelining bug: client sometimes sent new request while still waiting for 100-continue.
author Stephan Bosch <stephan@rename-it.nl>
date Mon, 08 Feb 2016 22:47:30 +0100
parents f40f5e721744
children ea58eba051b5
files src/lib-http/http-client-connection.c src/lib-http/http-client-private.h src/lib-http/http-client-request.c
diffstat 3 files changed, 12 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-http/http-client-connection.c	Mon Feb 08 22:45:54 2016 +0100
+++ b/src/lib-http/http-client-connection.c	Mon Feb 08 22:47:30 2016 +0100
@@ -369,7 +369,7 @@
 		array_count(&conn->request_wait_list)-1);
 	req = req_idx[0];
 
-	conn->payload_continue = TRUE;
+	req->payload_sync_continue = TRUE;
 	if (http_client_request_send_more(req, &error) < 0) {
 		http_client_connection_abort_temp_error(&conn,
 			HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
@@ -401,7 +401,7 @@
 		timeout_remove(&conn->to_idle);
 
 	req->conn = conn;
-	conn->payload_continue = FALSE;
+	req->payload_sync_continue = FALSE;
 	if (conn->peer->no_payload_sync)
 		req->payload_sync = FALSE;
 
@@ -742,7 +742,7 @@
 		   user agent MAY ignore unexpected 1xx responses.
 		 */
 		if (req->payload_sync && response.status == 100) {
-			if (conn->payload_continue) {
+			if (req->payload_sync_continue) {
 				http_client_connection_debug(conn,
 					"Got 100-continue response after timeout");
 				continue;
@@ -750,7 +750,7 @@
 
 			conn->peer->no_payload_sync = FALSE;
 			conn->peer->seen_100_response = TRUE;
-			conn->payload_continue = TRUE;
+			req->payload_sync_continue = TRUE;
 
 			http_client_connection_debug(conn,
 				"Got expected 100-continue response");
@@ -792,8 +792,10 @@
 			timeval_diff_msecs(&req->sent_time, &req->submit_time));
 
 		/* make sure connection output is unlocked if 100-continue failed */
-		if (req->payload_sync && !conn->payload_continue)
-			conn->output_locked = FALSE;	
+		if (req->payload_sync && !req->payload_sync_continue) {
+			http_client_connection_debug(conn, "Unlocked output");
+			conn->output_locked = FALSE;
+		}
 
 		/* remove request from queue */
 		array_delete(&conn->request_wait_list, 0, 1);
@@ -822,7 +824,7 @@
 			   blocks via http_client_request_send_payload()
 			   and we're not waiting for 100 continue */
 			if (!req->payload_wait ||
-				(req->payload_sync && !conn->payload_continue)) {
+				(req->payload_sync && !req->payload_sync_continue)) {
 				/* failed Expect: */
 				if (response.status == 417 && req->payload_sync) {
 					/* drop Expect: continue */
@@ -971,7 +973,7 @@
 			return 1;
 		}
 
-		if (!req->payload_sync || conn->payload_continue) {
+		if (!req->payload_sync || req->payload_sync_continue) {
 			if (http_client_request_send_more(req, &error) < 0) {
 				http_client_connection_abort_temp_error(&conn,
 					HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
--- a/src/lib-http/http-client-private.h	Mon Feb 08 22:45:54 2016 +0100
+++ b/src/lib-http/http-client-private.h	Mon Feb 08 22:47:30 2016 +0100
@@ -115,6 +115,7 @@
 	unsigned int have_hdr_user_agent:1;
 
 	unsigned int payload_sync:1;
+	unsigned int payload_sync_continue:1;
 	unsigned int payload_chunked:1;
 	unsigned int payload_wait:1;
 	unsigned int urgent:1;
@@ -160,8 +161,6 @@
 	unsigned int close_indicated:1;
 	unsigned int output_locked:1;       /* output is locked; no pipelining */
 	unsigned int output_broken:1;       /* output is broken; no more requests */
-	unsigned int payload_continue:1;    /* received 100-continue for current
-	                                        request */
 	unsigned int in_req_callback:1;  /* performin request callback (busy) */
 };
 
--- a/src/lib-http/http-client-request.c	Mon Feb 08 22:45:54 2016 +0100
+++ b/src/lib-http/http-client-request.c	Mon Feb 08 22:47:30 2016 +0100
@@ -1239,7 +1239,7 @@
 	   100 continue (there's no way to rewind the payload for a retry)
 	 */
 	if (req->payload_wait &&
-		(!req->payload_sync || req->conn->payload_continue))
+		(!req->payload_sync || req->payload_sync_continue))
 		return FALSE;
 	/* limit the number of attempts for each request */
 	if (req->attempts+1 >= req->client->set.max_attempts)