Browse Source

http2: Use KEEP_SEND_HOLD for flow control in HTTP/2

- use the defined, but so far not used, KEEP_SEND_HOLD bit for flow
  control based suspend of sending in transfers.

Prior to this change KEEP_SEND_PAUSE bit was used instead, but that can
interfere with pausing streams from the user side via curl_easy_pause.

Fixes https://github.com/curl/curl/issues/10751
Closes https://github.com/curl/curl/pull/10753
Stefan Eissing 1 year ago
parent
commit
06f65f771b
4 changed files with 9 additions and 10 deletions
  1. 6 6
      lib/http2.c
  2. 1 2
      lib/transfer.c
  3. 1 1
      lib/vquic/curl_ngtcp2.c
  4. 1 1
      lib/vquic/curl_quiche.c

+ 6 - 6
lib/http2.c

@@ -958,12 +958,12 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
     break;
   case NGHTTP2_WINDOW_UPDATE:
     DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv WINDOW_UPDATE", stream_id));
-    if((data_s->req.keepon & KEEP_SEND_PAUSE) &&
+    if((data_s->req.keepon & KEEP_SEND_HOLD) &&
        (data_s->req.keepon & KEEP_SEND)) {
-      data_s->req.keepon &= ~KEEP_SEND_PAUSE;
+      data_s->req.keepon &= ~KEEP_SEND_HOLD;
       drain_this(cf, data_s);
       Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
-      DEBUGF(LOG_CF(data, cf, "[h2sid=%u] unpausing after win update",
+      DEBUGF(LOG_CF(data, cf, "[h2sid=%u] un-holding after win update",
                     stream_id));
     }
     break;
@@ -2055,8 +2055,8 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
           /* We cannot upload more as the stream's remote window size
            * is 0. We need to receive WIN_UPDATEs before we can continue.
            */
-          data->req.keepon |= KEEP_SEND_PAUSE;
-          DEBUGF(LOG_CF(data, cf, "[h2sid=%u] pausing send as remote flow "
+          data->req.keepon |= KEEP_SEND_HOLD;
+          DEBUGF(LOG_CF(data, cf, "[h2sid=%u] holding send as remote flow "
                  "window is exhausted", stream->stream_id));
         }
     }
@@ -2189,7 +2189,7 @@ static int cf_h2_get_select_socks(struct Curl_cfilter *cf,
 
   /* 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) ||
+  if((((k->keepon & KEEP_SENDBITS) == KEEP_SEND) ||
       nghttp2_session_want_write(ctx->h2)) &&
      (nghttp2_session_get_remote_window_size(ctx->h2) &&
       nghttp2_session_get_stream_remote_window_size(ctx->h2,

+ 1 - 2
lib/transfer.c

@@ -1234,8 +1234,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
   }
 
   /* Now update the "done" boolean we return */
-  *done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND|
-                            KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE;
+  *done = (0 == (k->keepon&(KEEP_RECVBITS|KEEP_SENDBITS))) ? TRUE : FALSE;
   result = CURLE_OK;
 out:
   if(result)

+ 1 - 1
lib/vquic/curl_ngtcp2.c

@@ -903,7 +903,7 @@ static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf,
   rv |= GETSOCK_READSOCK(0);
 
   /* we're still uploading or the HTTP/2 layer wants to send data */
-  if((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND &&
+  if((k->keepon & KEEP_SENDBITS) == KEEP_SEND &&
      (!stream->h3out || stream->h3out->used < H3_SEND_SIZE) &&
      ngtcp2_conn_get_cwnd_left(ctx->qconn) &&
      ngtcp2_conn_get_max_data_left(ctx->qconn) &&

+ 1 - 1
lib/vquic/curl_quiche.c

@@ -950,7 +950,7 @@ static int cf_quiche_get_select_socks(struct Curl_cfilter *cf,
   rv |= GETSOCK_READSOCK(0);
 
   /* we're still uploading or the HTTP/3 layer wants to send data */
-  if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND)
+  if(((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
      && stream_is_writeable(cf, data))
     rv |= GETSOCK_WRITESOCK(0);