Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http3: curl stalls when stream is closed before sending all upload data #9122

Closed
tatsuhiro-t opened this issue Jul 8, 2022 · 1 comment
Closed
Labels
HTTP/3 h3 or quic related

Comments

@tatsuhiro-t
Copy link
Contributor

I did this

In order to reproduce this issue, the following tweak makes curl send invalid pseudo header field, and ngtcp2 server will respond with STOP_SENDING and RESET_STREAM, leading stream closure:

diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c
index 2d5f7f3c1..3d7552bfa 100644
--- a/lib/vquic/ngtcp2.c
+++ b/lib/vquic/ngtcp2.c
@@ -1361,7 +1361,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
   result = Curl_pseudo_headers(data, mem, len, &hreq);
   if(result)
     goto fail;
-  nheader = hreq->entries;
+  nheader = hreq->entries + 1;
 
   nva = malloc(sizeof(nghttp3_nv) * nheader);
   if(!nva) {
@@ -1370,13 +1370,18 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
   }
   else {
     unsigned int i;
-    for(i = 0; i < nheader; i++) {
+    for(i = 0; i < nheader - 1; i++) {
       nva[i].name = (unsigned char *)hreq->header[i].name;
       nva[i].namelen = hreq->header[i].namelen;
       nva[i].value = (unsigned char *)hreq->header[i].value;
       nva[i].valuelen = hreq->header[i].valuelen;
       nva[i].flags = NGHTTP3_NV_FLAG_NONE;
     }
+    nva[nheader - 1].name = (unsigned char *)":foo";
+    nva[nheader - 1].namelen = sizeof(":foo") - 1;
+    nva[nheader - 1].value = (unsigned char *)"foo";
+    nva[nheader - 1].valuelen = sizeof("foo") - 1;
+    nva[nheader - 1].flags = NGHTTP3_NV_FLAG_NONE;
   }
 
   switch(data->state.httpreq) {
curl --http3 https://127.0.0.1 -T uploadfile -v
...
* ngh3_stream_recv returns 0 bytes and EAGAIN
* ngh3_stream_send() wants to send 65536 bytes
* cb_h3_stream_close CALLED
* ngh3_stream_send() wants to send 65536 bytes
* Curl_readwrite: forcibly told to drain data
* Curl_readwrite: forcibly told to drain data
* Curl_readwrite: forcibly told to drain data
* Curl_readwrite: forcibly told to drain data
* Curl_readwrite: forcibly told to drain data
(repeated)

Another way to reproduce this issue does not require any modification to curl. Make server return response without waiting for request data, which may trigger STOP_SENDING from server. ngtcp2 server --early-response does this.

I expected the following

curl stops with some indication of error.

curl/libcurl version

[curl -V output]
curl 7.85.0-DEV
master branch

operating system

linux

@tatsuhiro-t
Copy link
Contributor Author

Meanwhile, HTTP/2 works well in these cases. We need similar treatment for HTTP/3 as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
HTTP/3 h3 or quic related
Development

Successfully merging a pull request may close this issue.

2 participants