diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerTransport.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerTransport.java index 7d192b16943..8b5d8e6405f 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerTransport.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerTransport.java @@ -864,6 +864,19 @@ public void data(boolean inFinished, int streamId, BufferedSource in, int length // concerned with the window being exceeded at this point. in.require(length); + // connection window update + // The connection window must be updated even if the stream is in an errored state. + // See RFC 9113, section 6.9 + connectionUnacknowledgedBytesRead += paddedLength; + if (connectionUnacknowledgedBytesRead + >= config.flowControlWindow * Utils.DEFAULT_WINDOW_UPDATE_RATIO) { + synchronized (lock) { + frameWriter.windowUpdate(0, connectionUnacknowledgedBytesRead); + frameWriter.flush(); + } + connectionUnacknowledgedBytesRead = 0; + } + synchronized (lock) { StreamState stream = streams.get(streamId); if (stream == null) { @@ -887,17 +900,6 @@ public void data(boolean inFinished, int streamId, BufferedSource in, int length buf.write(in.getBuffer(), length); stream.inboundDataReceived(buf, length, paddedLength - length, inFinished); } - - // connection window update - connectionUnacknowledgedBytesRead += paddedLength; - if (connectionUnacknowledgedBytesRead - >= config.flowControlWindow * Utils.DEFAULT_WINDOW_UPDATE_RATIO) { - synchronized (lock) { - frameWriter.windowUpdate(0, connectionUnacknowledgedBytesRead); - frameWriter.flush(); - } - connectionUnacknowledgedBytesRead = 0; - } } @Override diff --git a/okhttp/src/test/java/io/grpc/okhttp/OkHttpServerTransportTest.java b/okhttp/src/test/java/io/grpc/okhttp/OkHttpServerTransportTest.java index 00db6e1d339..1456f421156 100644 --- a/okhttp/src/test/java/io/grpc/okhttp/OkHttpServerTransportTest.java +++ b/okhttp/src/test/java/io/grpc/okhttp/OkHttpServerTransportTest.java @@ -1067,6 +1067,9 @@ public void windowUpdate() throws Exception { writeDataDirectly(clientWriterSink, FLAG_PADDED | FLAG_END_STREAM, 1, message, 100); clientFrameWriter.flush(); assertThat(clientFrameReader.nextFrame(clientFramesRead)).isTrue(); + // Receive window update for the padded data size before stream reset + verify(clientFramesRead).windowUpdate(0, expectedConsumed + 100); + assertThat(clientFrameReader.nextFrame(clientFramesRead)).isTrue(); verify(clientFramesRead).rstStream(eq(1), eq(ErrorCode.FLOW_CONTROL_ERROR)); clientFrameWriter.rstStream(3, ErrorCode.CANCEL); pingPong();