You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2022/01/01 17:31:12 UTC
[httpcomponents-core] branch master updated: HTTPCORE-707: H2 connections incorrectly enforce the frame size max limit based on local settings instead of remote ones
This is an automated email from the ASF dual-hosted git repository.
olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
The following commit(s) were added to refs/heads/master by this push:
new a3c77ef HTTPCORE-707: H2 connections incorrectly enforce the frame size max limit based on local settings instead of remote ones
a3c77ef is described below
commit a3c77ef69d4449881a55f43d600e40029a2ee6fd
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Fri Dec 31 15:00:42 2021 +0100
HTTPCORE-707: H2 connections incorrectly enforce the frame size max limit based on local settings instead of remote ones
---
.../http2/impl/nio/AbstractH2StreamMultiplexer.java | 5 +++++
.../hc/core5/http2/impl/nio/FrameOutputBuffer.java | 21 +++++++++++++--------
.../core5/http2/impl/nio/TestFrameInOutBuffers.java | 2 +-
3 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
index 02ae8b9..f6ce609 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
@@ -1218,6 +1218,11 @@ abstract class AbstractH2StreamMultiplexer implements Identifiable, HttpConnecti
final int delta = remoteConfig.getInitialWindowSize() - initOutputWinSize;
initOutputWinSize = remoteConfig.getInitialWindowSize();
+ final int maxFrameSize = remoteConfig.getMaxFrameSize();
+ if (maxFrameSize > localConfig.getMaxFrameSize()) {
+ outputBuffer.expand(maxFrameSize);
+ }
+
if (delta != 0) {
if (!streamMap.isEmpty()) {
for (final Iterator<Map.Entry<Integer, H2Stream>> it = streamMap.entrySet().iterator(); it.hasNext(); ) {
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/FrameOutputBuffer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/FrameOutputBuffer.java
index aa76a13..f20edfb 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/FrameOutputBuffer.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/FrameOutputBuffer.java
@@ -31,8 +31,6 @@ import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.WritableByteChannel;
-import org.apache.hc.core5.http2.H2ConnectionException;
-import org.apache.hc.core5.http2.H2Error;
import org.apache.hc.core5.http2.H2TransportMetrics;
import org.apache.hc.core5.http2.frame.FrameConsts;
import org.apache.hc.core5.http2.frame.RawFrame;
@@ -47,8 +45,8 @@ import org.apache.hc.core5.util.Args;
public final class FrameOutputBuffer {
private final BasicH2TransportMetrics metrics;
- private final int maxFramePayloadSize;
- private final ByteBuffer buffer;
+ private volatile int maxFramePayloadSize;
+ private volatile ByteBuffer buffer;
public FrameOutputBuffer(final BasicH2TransportMetrics metrics, final int maxFramePayloadSize) {
Args.notNull(metrics, "HTTP2 transport metrics");
@@ -62,14 +60,21 @@ public final class FrameOutputBuffer {
this(new BasicH2TransportMetrics(), maxFramePayloadSize);
}
+ public void expand(final int maxFramePayloadSize) {
+ this.maxFramePayloadSize = maxFramePayloadSize;
+ final ByteBuffer newBuffer = ByteBuffer.allocate(FrameConsts.HEAD_LEN + maxFramePayloadSize);
+ if (buffer.position() > 0) {
+ buffer.flip();
+ newBuffer.put(buffer);
+ }
+ buffer = newBuffer;
+ }
+
public void write(final RawFrame frame, final WritableByteChannel channel) throws IOException {
Args.notNull(frame, "Frame");
final ByteBuffer payload = frame.getPayload();
- if (payload != null && payload.remaining() > maxFramePayloadSize) {
- throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Frame size exceeds maximum");
- }
-
+ Args.check(payload == null || payload.remaining() <= maxFramePayloadSize, "Frame size exceeds maximum");
buffer.putInt((payload != null ? payload.remaining() << 8 : 0) | (frame.getType() & 0xff));
buffer.put((byte) (frame.getFlags() & 0xff));
buffer.putInt(frame.getStreamId());
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestFrameInOutBuffers.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestFrameInOutBuffers.java
index 6465ad3..f1500f1 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestFrameInOutBuffers.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestFrameInOutBuffers.java
@@ -259,7 +259,7 @@ public class TestFrameInOutBuffers {
final RawFrame frame = new RawFrame(FrameType.DATA.getValue(), 0, 1,
ByteBuffer.wrap(new byte[2048]));
- Assertions.assertThrows(H2ConnectionException.class, () ->
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
outbuffer.write(frame, writableChannel));
}