Commit cde0cf7c authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa Committed by Daniel Stenberg
Browse files

Fix bug that HTTP/2 hangs if whole response body is read with headers

For HTTP/2, we may read up everything including responde body with
header fields in Curl_http_readwrite_headers. If no content-length is
provided, curl waits for the connection close, which we emulate it
using conn->proto.httpc.closed = TRUE. The thing is if we read
everything, then http2_recv won't be called and we cannot signal the
HTTP/2 stream has closed. As a workaround, we return nonzero from
data_pending to call http2_recv.
parent 53f1f4a1
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -514,6 +514,10 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,

  (void)sockindex; /* we always do HTTP2 on sockindex 0 */

  if(httpc->closed) {
    return 0;
  }

  /* Nullify here because we call nghttp2_session_send() and they
     might refer to the old buffer. */
  httpc->upload_mem = NULL;
+10 −1
Original line number Diff line number Diff line
@@ -310,7 +310,16 @@ static int data_pending(const struct connectdata *conn)
  /* in the case of libssh2, we can never be really sure that we have emptied
     its internal buffers so we MUST always try until we get EAGAIN back */
  return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
    Curl_ssl_data_pending(conn, FIRSTSOCKET);
    Curl_ssl_data_pending(conn, FIRSTSOCKET) ||
    /* For HTTP/2, we may read up everything including responde body
       with header fields in Curl_http_readwrite_headers. If no
       content-length is provided, curl waits for the connection
       close, which we emulate it using conn->proto.httpc.closed =
       TRUE. The thing is if we read everything, then http2_recv won't
       be called and we cannot signal the HTTP/2 stream has closed. As
       a workaround, we return nonzero here to call http2_recv. */
    ((conn->handler->protocol&CURLPROTO_HTTP) && conn->httpversion == 20 &&
     conn->proto.httpc.closed);
}

static void read_rewind(struct connectdata *conn,