From 6883180fa5772f94cb70988fa58ed52cf9ddea9d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 10 Feb 2022 23:28:46 +0100 Subject: [PATCH] quiche: when *recv_body() returns data, drain it before polling again Assisted-by: Lucas Pardue Closes #8429 --- lib/vquic/quiche.c | 106 +++++++++++++++++++++++++-------------------- lib/vquic/quiche.h | 1 + 2 files changed, 61 insertions(+), 46 deletions(-) diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c index 7104af3842..53ad4fb9bb 100644 --- a/lib/vquic/quiche.c +++ b/lib/vquic/quiche.c @@ -589,59 +589,73 @@ static ssize_t h3_stream_recv(struct Curl_easy *data, return -1; } - while(recvd < 0) { - int64_t s = quiche_h3_conn_poll(qs->h3c, qs->conn, &ev); - if(s < 0) - /* nothing more to do */ - break; - - if(s != stream->stream3_id) { - /* another transfer, ignore for now */ - infof(data, "Got h3 for stream %u, expects %u", - s, stream->stream3_id); - continue; + if(qs->h3_recving) { + /* body receiving state */ + rcode = quiche_h3_recv_body(qs->h3c, qs->conn, stream->stream3_id, + (unsigned char *)buf, buffersize); + if(rcode <= 0) { + recvd = -1; + qs->h3_recving = FALSE; } - - switch(quiche_h3_event_type(ev)) { - case QUICHE_H3_EVENT_HEADERS: - rc = quiche_h3_event_for_each_header(ev, cb_each_header, &headers); - if(rc) { - *curlcode = rc; - failf(data, "Error in HTTP/3 response header"); + else + recvd = rcode; + } + else { + while(recvd < 0) { + int64_t s = quiche_h3_conn_poll(qs->h3c, qs->conn, &ev); + if(s < 0) + /* nothing more to do */ break; + + if(s != stream->stream3_id) { + /* another transfer, ignore for now */ + infof(data, "Got h3 for stream %u, expects %u", + s, stream->stream3_id); + continue; } - recvd = headers.nlen; - break; - case QUICHE_H3_EVENT_DATA: - if(!stream->firstbody) { - /* add a header-body separator CRLF */ - buf[0] = '\r'; - buf[1] = '\n'; - buf += 2; - buffersize -= 2; - stream->firstbody = TRUE; - recvd = 2; /* two bytes already */ - } - else - recvd = 0; - rcode = quiche_h3_recv_body(qs->h3c, qs->conn, s, (unsigned char *)buf, - buffersize); - if(rcode <= 0) { - recvd = -1; + + switch(quiche_h3_event_type(ev)) { + case QUICHE_H3_EVENT_HEADERS: + rc = quiche_h3_event_for_each_header(ev, cb_each_header, &headers); + if(rc) { + *curlcode = rc; + failf(data, "Error in HTTP/3 response header"); + break; + } + recvd = headers.nlen; + break; + case QUICHE_H3_EVENT_DATA: + if(!stream->firstbody) { + /* add a header-body separator CRLF */ + buf[0] = '\r'; + buf[1] = '\n'; + buf += 2; + buffersize -= 2; + stream->firstbody = TRUE; + recvd = 2; /* two bytes already */ + } + else + recvd = 0; + rcode = quiche_h3_recv_body(qs->h3c, qs->conn, s, (unsigned char *)buf, + buffersize); + if(rcode <= 0) { + recvd = -1; + break; + } + qs->h3_recving = TRUE; + recvd += rcode; + break; + + case QUICHE_H3_EVENT_FINISHED: + streamclose(conn, "End of stream"); + recvd = 0; /* end of stream */ + break; + default: break; } - recvd += rcode; - break; - case QUICHE_H3_EVENT_FINISHED: - streamclose(conn, "End of stream"); - recvd = 0; /* end of stream */ - break; - default: - break; + quiche_h3_event_free(ev); } - - quiche_h3_event_free(ev); } if(flush_egress(data, sockfd, qs)) { *curlcode = CURLE_SEND_ERROR; diff --git a/lib/vquic/quiche.h b/lib/vquic/quiche.h index 4a079d37bb..759a20bbac 100644 --- a/lib/vquic/quiche.h +++ b/lib/vquic/quiche.h @@ -46,6 +46,7 @@ struct quicsocket { uint32_t version; SSL_CTX *sslctx; SSL *ssl; + bool h3_recving; /* TRUE when in h3-body-reading state */ }; #endif -- 2.47.3