]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
quiche: when *recv_body() returns data, drain it before polling again
authorDaniel Stenberg <daniel@haxx.se>
Thu, 10 Feb 2022 22:28:46 +0000 (23:28 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 11 Feb 2022 07:48:30 +0000 (08:48 +0100)
Assisted-by: Lucas Pardue
Closes #8429

lib/vquic/quiche.c
lib/vquic/quiche.h

index 7104af38425a6f7610c95d4e3d7e76143e619b01..53ad4fb9bb14e4bee3a10e4ba791074347dd3c3c 100644 (file)
@@ -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;
index 4a079d37bb5221a2c658512f1530347eb645c37a..759a20bbac3411c224fc4f7e8d8d74fefbc14ffe 100644 (file)
@@ -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