]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: client: Fixed pipelining bug: client sometimes sent new request while still...
authorStephan Bosch <stephan@rename-it.nl>
Mon, 8 Feb 2016 21:47:30 +0000 (22:47 +0100)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 10 Feb 2016 11:55:25 +0000 (13:55 +0200)
src/lib-http/http-client-connection.c
src/lib-http/http-client-private.h
src/lib-http/http-client-request.c

index 0947a2a234fbd59cbae2ded39e41b4e376bc8861..3931c5cd52330615f453b5564359e72053e5e329 100644 (file)
@@ -369,7 +369,7 @@ http_client_connection_continue_timeout(struct http_client_connection *conn)
                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 @@ int http_client_connection_next_request(struct http_client_connection *conn)
                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 @@ static void http_client_connection_input(struct connection *_conn)
                   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 @@ static void http_client_connection_input(struct connection *_conn)
 
                        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 @@ static void http_client_connection_input(struct connection *_conn)
                        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 @@ static void http_client_connection_input(struct connection *_conn)
                           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 @@ int http_client_connection_output(struct http_client_connection *conn)
                        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,
index 5fb3916343bae4b7edab122dcade548497e8dea9..67658153f6e0e32d8ee7927bef3f25a036fa0d0c 100644 (file)
@@ -115,6 +115,7 @@ struct http_client_request {
        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 @@ struct http_client_connection {
        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) */
 };
 
index e8f3b64d3d6c07b582d5dc8e3740042fc29436a9..c1bc49e53234d2a7e4cdb31ea0963794c969b1eb 100644 (file)
@@ -1239,7 +1239,7 @@ bool http_client_request_try_retry(struct http_client_request *req)
           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)