]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http2: make getsock not wait for write if there's no remote window
authorDaniel Stenberg <daniel@haxx.se>
Mon, 11 Oct 2021 14:56:51 +0000 (16:56 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 12 Oct 2021 09:19:22 +0000 (11:19 +0200)
While uploading, check for remote window availability in the getsock
function so that we don't wait for a writable socket if no data can be
sent.

Reported-by: Steini2000 on github
Fixes #7821
Closes #7839

lib/http2.c

index 6d63f43636a52e1a84054c8f50904fc29142002b..992fbbb26db1078052589e48b4ca4c57dc66cf4f 100644 (file)
@@ -100,6 +100,7 @@ static int http2_getsock(struct Curl_easy *data,
   const struct http_conn *c = &conn->proto.httpc;
   struct SingleRequest *k = &data->req;
   int bitmap = GETSOCK_BLANK;
+  struct HTTP *stream = data->req.p.http;
 
   sock[0] = conn->sock[FIRSTSOCKET];
 
@@ -108,9 +109,13 @@ static int http2_getsock(struct Curl_easy *data,
        frame so we should always be ready for one */
     bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
 
-  /* we're still uploading or the HTTP/2 layer wants to send data */
-  if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
-     nghttp2_session_want_write(c->h2))
+  /* we're (still uploading OR the HTTP/2 layer wants to send data) AND
+     there's a window to send data in */
+  if((((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
+      nghttp2_session_want_write(c->h2)) &&
+     (nghttp2_session_get_remote_window_size(c->h2) &&
+      nghttp2_session_get_stream_remote_window_size(c->h2,
+                                                    stream->stream_id)))
     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
 
   return bitmap;
@@ -1953,8 +1958,19 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
       nghttp2_session_resume_data(h2, stream->stream_id);
     }
 
-    H2BUGF(infof(data, "http2_send returns %zu for stream %u", len,
-                 stream->stream_id));
+#ifdef DEBUG_HTTP2
+    if(!len) {
+      infof(data, "http2_send: easy %p (stream %u) win %u/%u",
+            data, stream->stream_id,
+            nghttp2_session_get_remote_window_size(httpc->h2),
+            nghttp2_session_get_stream_remote_window_size(httpc->h2,
+                                                          stream->stream_id)
+        );
+
+    }
+    infof(data, "http2_send returns %zu for stream %u", len,
+          stream->stream_id);
+#endif
     return len;
   }