diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameCodec.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameCodec.java index a1458ad6f1..7c16edc754 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameCodec.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameCodec.java @@ -305,10 +305,8 @@ public class Http2FrameCodec extends Http2ConnectionHandler { } private void increaseInitialConnectionWindow(int deltaBytes) throws Http2Exception { - Http2LocalFlowController localFlow = connection().local().flowController(); - int targetConnectionWindow = localFlow.initialWindowSize() + deltaBytes; - localFlow.incrementWindowSize(connection().connectionStream(), deltaBytes); - localFlow.initialWindowSize(targetConnectionWindow); + // The LocalFlowController is responsible for detecting over/under flow. + connection().local().flowController().incrementWindowSize(connection().connectionStream(), deltaBytes); } final boolean consumeBytes(int streamId, int bytes) throws Http2Exception { diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameCodecTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameCodecTest.java index e3a816c0dd..a3a422ca83 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameCodecTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameCodecTest.java @@ -478,16 +478,38 @@ public class Http2FrameCodecTest { } @Test - public void streamZeroWindowUpdateIncrementsConnectionWindow() throws Exception { + public void streamZeroWindowUpdateIncrementsConnectionWindow() throws Http2Exception { Http2Connection connection = frameCodec.connection(); Http2LocalFlowController localFlow = connection.local().flowController(); int initialWindowSizeBefore = localFlow.initialWindowSize(); + Http2Stream connectionStream = connection.connectionStream(); + int connectionWindowSizeBefore = localFlow.windowSize(connectionStream); + // We only replenish the flow control window after the amount consumed drops below the following threshold. + // We make the threshold very "high" so that window updates will be sent when the delta is relatively small. + ((DefaultHttp2LocalFlowController) localFlow).windowUpdateRatio(connectionStream, .999f); int windowUpdate = 1024; channel.write(new DefaultHttp2WindowUpdateFrame(windowUpdate)); - assertEquals(initialWindowSizeBefore + windowUpdate, localFlow.initialWindowSize()); + // The initial window size is only changed by Http2Settings, so it shouldn't change. + assertEquals(initialWindowSizeBefore, localFlow.initialWindowSize()); + // The connection window should be increased by the delta amount. + assertEquals(connectionWindowSizeBefore + windowUpdate, localFlow.windowSize(connectionStream)); + } + + @Test + public void windowUpdateDoesNotOverflowConnectionWindow() { + Http2Connection connection = frameCodec.connection(); + Http2LocalFlowController localFlow = connection.local().flowController(); + int initialWindowSizeBefore = localFlow.initialWindowSize(); + + channel.write(new DefaultHttp2WindowUpdateFrame(Integer.MAX_VALUE)); + + // The initial window size is only changed by Http2Settings, so it shouldn't change. + assertEquals(initialWindowSizeBefore, localFlow.initialWindowSize()); + // The connection window should be increased by the delta amount. + assertEquals(Integer.MAX_VALUE, localFlow.windowSize(connection.connectionStream())); } @Test