From c338c1a15364329817c48b9f2f0c2fc3dfd8844d Mon Sep 17 00:00:00 2001 From: OlexYarm Date: Fri, 6 Oct 2023 12:07:44 -0400 Subject: [PATCH 1/4] Fixed issue 10305 Embedded Jetty server fails to start when requests log path in RequestLogWriter contains not existed directory Changed error message when requests log path in RequestLogWriter contains not existed directory. --- .../jetty/util/RolloverFileOutputStream.java | 14 ++++++- .../util/RolloverFileOutputStreamTest.java | 41 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/RolloverFileOutputStream.java b/jetty-util/src/main/java/org/eclipse/jetty/util/RolloverFileOutputStream.java index e30b443acf1d..94bfae53f898 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/RolloverFileOutputStream.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/RolloverFileOutputStream.java @@ -233,9 +233,19 @@ void setFile(ZonedDateTime now) File file = new File(_filename); _filename = file.getCanonicalPath(); file = new File(_filename); - File dir = new File(file.getParent()); - if (!dir.isDirectory() || !dir.canWrite()) + File dir = file.getParentFile(); + if (!dir.exists()) + { + throw new IOException("Log directory does not exist. Path=" + dir); + } + else if (!dir.isDirectory()) + { + throw new IOException("Path for Log directory is not a directory. Path=" + dir); + } + else if (!dir.canWrite()) + { throw new IOException("Cannot write log directory " + dir); + } // Is this a rollover file? String filename = file.getName(); diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java index ee3872f98ea0..7c1f67106430 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java @@ -181,6 +181,47 @@ public void testMidnightRolloverCalcSydneyDSTEnd() assertSequence(midnight, expected); } + @Test + public void testMissingDirectory() + { + + ZoneId zone = toZoneId("Australia/Sydney"); + ZonedDateTime now = toDateTime("2016.04.10-08:30:12.3 AM AEDT", zone); + String templateString = "missingDir/test-rofos-yyyy_mm_dd.log"; + String excMessageExpected = "Log directory does not exist."; + + try (RolloverFileOutputStream rofos = + new RolloverFileOutputStream(templateString, false, 3, TimeZone.getTimeZone(zone), null, null, now)) + { + rofos.write("TICK".getBytes()); + rofos.flush(); + } + catch (Exception ex) + { + boolean exClassOK = false; + if (ex instanceof java.io.IOException) + { + exClassOK = true; + } + assertThat("Exception Type", exClassOK, is(true)); + + String excMessageActual = ex.getMessage(); + boolean messageOK = false; + if (excMessageActual != null) + { + excMessageActual = excMessageActual.trim(); + if (!excMessageActual.isEmpty()) + { + if (excMessageActual.contains(excMessageExpected)) + { + messageOK = true; + } + } + } + assertThat("Exception Message", messageOK, is(true)); + } + } + @Test public void testFileHandling() throws Exception { From 40a31b839475f20d9b8639c738444d9fe3307462 Mon Sep 17 00:00:00 2001 From: OlexYarm Date: Mon, 16 Oct 2023 18:26:59 -0400 Subject: [PATCH 2/4] Update RolloverFileOutputStreamTest.java Simplified test class as suggested --- .../util/RolloverFileOutputStreamTest.java | 43 ++++++------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java index 7c1f67106430..fbe120cd9450 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java @@ -36,7 +36,10 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertNotNull; @ExtendWith(WorkDirExtension.class) public class RolloverFileOutputStreamTest @@ -185,41 +188,21 @@ public void testMidnightRolloverCalcSydneyDSTEnd() public void testMissingDirectory() { - ZoneId zone = toZoneId("Australia/Sydney"); - ZonedDateTime now = toDateTime("2016.04.10-08:30:12.3 AM AEDT", zone); String templateString = "missingDir/test-rofos-yyyy_mm_dd.log"; - String excMessageExpected = "Log directory does not exist."; - - try (RolloverFileOutputStream rofos = - new RolloverFileOutputStream(templateString, false, 3, TimeZone.getTimeZone(zone), null, null, now)) + String excMessageActual = null; + Throwable error = null; + try (RolloverFileOutputStream rofos = new RolloverFileOutputStream(templateString)) { - rofos.write("TICK".getBytes()); - rofos.flush(); + throw new IllegalStateException(); } - catch (Exception ex) + catch (Throwable t) { - boolean exClassOK = false; - if (ex instanceof java.io.IOException) - { - exClassOK = true; - } - assertThat("Exception Type", exClassOK, is(true)); - - String excMessageActual = ex.getMessage(); - boolean messageOK = false; - if (excMessageActual != null) - { - excMessageActual = excMessageActual.trim(); - if (!excMessageActual.isEmpty()) - { - if (excMessageActual.contains(excMessageExpected)) - { - messageOK = true; - } - } - } - assertThat("Exception Message", messageOK, is(true)); + error = t; + excMessageActual = t.getMessage(); } + assertNotNull(error); + assertThat(error, instanceOf(IOException.class)); + assertThat(excMessageActual, containsString("Log directory does not exist.")); } @Test From 4b6627ae0ccd33c85684bff395a5d28b1b6b653f Mon Sep 17 00:00:00 2001 From: OlexYarm Date: Mon, 16 Oct 2023 18:48:09 -0400 Subject: [PATCH 3/4] Update RolloverFileOutputStreamTest.java more simplification --- .../eclipse/jetty/util/RolloverFileOutputStreamTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java index fbe120cd9450..c19bc4184fe5 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java @@ -189,8 +189,7 @@ public void testMissingDirectory() { String templateString = "missingDir/test-rofos-yyyy_mm_dd.log"; - String excMessageActual = null; - Throwable error = null; + Throwable error; try (RolloverFileOutputStream rofos = new RolloverFileOutputStream(templateString)) { throw new IllegalStateException(); @@ -198,11 +197,11 @@ public void testMissingDirectory() catch (Throwable t) { error = t; - excMessageActual = t.getMessage(); } assertNotNull(error); assertThat(error, instanceOf(IOException.class)); - assertThat(excMessageActual, containsString("Log directory does not exist.")); + error.getMessage(); + assertThat(error.getMessage(), containsString("Log directory does not exist.")); } @Test From 8c94490e186f76e41c56b1bd4dc246291b46462f Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Wed, 18 Oct 2023 17:06:56 +0200 Subject: [PATCH 4/4] Fixes #10390 - jetty http3 client and nghttpx. (#10744) Fixed handling of long settings values, so that they do not overflow. Added logging for GREASE cases. Signed-off-by: Simone Bordet --- .../client/internal/ClientHTTP3Session.java | 24 +++++++--- .../client/internal/HTTP3SessionClient.java | 2 +- .../eclipse/jetty/http3/internal/Grease.java | 48 +++++++++++++++++++ .../jetty/http3/internal/HTTP3ErrorCode.java | 6 +-- .../http3/internal/parser/ControlParser.java | 4 +- .../http3/internal/parser/MessageParser.java | 4 +- .../server/internal/ServerHTTP3Session.java | 24 +++++++--- 7 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/Grease.java diff --git a/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/internal/ClientHTTP3Session.java b/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/internal/ClientHTTP3Session.java index bf798135be29..4143fb56139f 100644 --- a/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/internal/ClientHTTP3Session.java +++ b/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/internal/ClientHTTP3Session.java @@ -24,6 +24,7 @@ import org.eclipse.jetty.http3.internal.ControlFlusher; import org.eclipse.jetty.http3.internal.DecoderStreamConnection; import org.eclipse.jetty.http3.internal.EncoderStreamConnection; +import org.eclipse.jetty.http3.internal.Grease; import org.eclipse.jetty.http3.internal.HTTP3ErrorCode; import org.eclipse.jetty.http3.internal.InstructionFlusher; import org.eclipse.jetty.http3.internal.InstructionHandler; @@ -63,7 +64,7 @@ public ClientHTTP3Session(HTTP3Configuration configuration, ClientQuicSession qu if (LOG.isDebugEnabled()) LOG.debug("initializing HTTP/3 streams"); - long encoderStreamId = getQuicSession().newStreamId(StreamType.CLIENT_UNIDIRECTIONAL); + long encoderStreamId = newStreamId(StreamType.CLIENT_UNIDIRECTIONAL); QuicStreamEndPoint encoderEndPoint = openInstructionEndPoint(encoderStreamId); InstructionFlusher encoderInstructionFlusher = new InstructionFlusher(quicSession, encoderEndPoint, EncoderStreamConnection.STREAM_TYPE); encoder = new QpackEncoder(new InstructionHandler(encoderInstructionFlusher)); @@ -72,7 +73,7 @@ public ClientHTTP3Session(HTTP3Configuration configuration, ClientQuicSession qu if (LOG.isDebugEnabled()) LOG.debug("created encoder stream #{} on {}", encoderStreamId, encoderEndPoint); - long decoderStreamId = getQuicSession().newStreamId(StreamType.CLIENT_UNIDIRECTIONAL); + long decoderStreamId = newStreamId(StreamType.CLIENT_UNIDIRECTIONAL); QuicStreamEndPoint decoderEndPoint = openInstructionEndPoint(decoderStreamId); InstructionFlusher decoderInstructionFlusher = new InstructionFlusher(quicSession, decoderEndPoint, DecoderStreamConnection.STREAM_TYPE); decoder = new QpackDecoder(new InstructionHandler(decoderInstructionFlusher)); @@ -80,7 +81,7 @@ public ClientHTTP3Session(HTTP3Configuration configuration, ClientQuicSession qu if (LOG.isDebugEnabled()) LOG.debug("created decoder stream #{} on {}", decoderStreamId, decoderEndPoint); - long controlStreamId = getQuicSession().newStreamId(StreamType.CLIENT_UNIDIRECTIONAL); + long controlStreamId = newStreamId(StreamType.CLIENT_UNIDIRECTIONAL); QuicStreamEndPoint controlEndPoint = openControlEndPoint(controlStreamId); controlFlusher = new ControlFlusher(quicSession, controlEndPoint, true); addBean(controlFlusher); @@ -106,6 +107,11 @@ public HTTP3SessionClient getSessionClient() return session; } + public long newStreamId(StreamType streamType) + { + return getQuicSession().newStreamId(streamType); + } + @Override protected void onStart() { @@ -171,21 +177,27 @@ public void onSettings(SettingsFrame frame) { if (key == SettingsFrame.MAX_TABLE_CAPACITY) { - int maxTableCapacity = value.intValue(); + int maxTableCapacity = (int)Math.min(value, Integer.MAX_VALUE); encoder.setMaxTableCapacity(maxTableCapacity); encoder.setTableCapacity(Math.min(maxTableCapacity, configuration.getMaxEncoderTableCapacity())); } else if (key == SettingsFrame.MAX_FIELD_SECTION_SIZE) { // Must cap the maxHeaderSize to avoid large allocations. - int maxHeadersSize = Math.min(value.intValue(), configuration.getMaxRequestHeadersSize()); + int maxHeadersSize = (int)Math.min(value, configuration.getMaxResponseHeadersSize()); encoder.setMaxHeadersSize(maxHeadersSize); } else if (key == SettingsFrame.MAX_BLOCKED_STREAMS) { - int maxBlockedStreams = value.intValue(); + int maxBlockedStreams = (int)Math.min(value, Integer.MAX_VALUE); encoder.setMaxBlockedStreams(maxBlockedStreams); } + else + { + // SPEC: grease and unknown settings are ignored. + if (LOG.isDebugEnabled()) + LOG.debug("ignored {} setting {}={}", Grease.isGreaseValue(key) ? "grease" : "unknown", key, value); + } }); } diff --git a/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/internal/HTTP3SessionClient.java b/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/internal/HTTP3SessionClient.java index a71940360462..699a477bc3d5 100644 --- a/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/internal/HTTP3SessionClient.java +++ b/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/internal/HTTP3SessionClient.java @@ -93,7 +93,7 @@ public void onSettings(SettingsFrame frame) @Override public CompletableFuture newRequest(HeadersFrame frame, Stream.Client.Listener listener) { - long streamId = getProtocolSession().getQuicSession().newStreamId(StreamType.CLIENT_BIDIRECTIONAL); + long streamId = getProtocolSession().newStreamId(StreamType.CLIENT_BIDIRECTIONAL); return newRequest(streamId, frame, listener); } diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/Grease.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/Grease.java new file mode 100644 index 000000000000..3261f441f1f7 --- /dev/null +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/Grease.java @@ -0,0 +1,48 @@ +// +// ======================================================================== +// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.http3.internal; + +import java.util.concurrent.ThreadLocalRandom; + +/** + *

A class to support GREASE (RFC 8701) in HTTP/3.

+ *

HTTP/3 GREASE values have the form {@code 0x1F * N + 0x21} with non negative values of {@code N}.

+ */ +public class Grease +{ + /** + * @param value the value to test + * @return whether the value is a GREASE value as defined by HTTP/3 + */ + public static boolean isGreaseValue(long value) + { + if (value < 0) + return false; + return (value - 0x21) % 0x1F == 0; + } + + /** + * @return a random grease value as defined by HTTP/3 + */ + public static long generateGreaseValue() + { + // This constant avoids to overflow VarLenInt. + long n = ThreadLocalRandom.current().nextLong(0x210842108421084L); + return 0x1F * n + 0x21; + } + + private Grease() + { + } +} diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/HTTP3ErrorCode.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/HTTP3ErrorCode.java index b7887ba16099..90fca1039ada 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/HTTP3ErrorCode.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/HTTP3ErrorCode.java @@ -13,8 +13,6 @@ package org.eclipse.jetty.http3.internal; -import java.util.concurrent.ThreadLocalRandom; - public enum HTTP3ErrorCode { NO_ERROR(0x100), @@ -45,9 +43,7 @@ public enum HTTP3ErrorCode public static long randomReservedCode() { // SPEC: reserved errors have the form 0x1F * n + 0x21. - // This constant avoids to overflow VarLenInt, which is how an error code is encoded. - long n = ThreadLocalRandom.current().nextLong(0x210842108421084L); - return 0x1F * n + 0x21; + return Grease.generateGreaseValue(); } public long code() diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ControlParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ControlParser.java index 885765807691..0bfa5041af4e 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ControlParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ControlParser.java @@ -17,6 +17,7 @@ import java.nio.ByteBuffer; import org.eclipse.jetty.http3.frames.FrameType; +import org.eclipse.jetty.http3.internal.Grease; import org.eclipse.jetty.http3.internal.HTTP3ErrorCode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -91,8 +92,9 @@ public void parse(ByteBuffer buffer) return; } + // SPEC: grease and unknown frame types are ignored. if (LOG.isDebugEnabled()) - LOG.debug("ignoring unknown frame type {}", Long.toHexString(frameType)); + LOG.debug("ignoring {} frame type {}", Grease.isGreaseValue(frameType) ? "grease" : "unknown", Long.toHexString(frameType)); BodyParser.Result result = unknownBodyParser.parse(buffer); if (result == BodyParser.Result.NO_FRAME) diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/MessageParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/MessageParser.java index 113b2000b23d..f06ff0d3e4b3 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/MessageParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/MessageParser.java @@ -19,6 +19,7 @@ import java.util.function.UnaryOperator; import org.eclipse.jetty.http3.frames.FrameType; +import org.eclipse.jetty.http3.internal.Grease; import org.eclipse.jetty.http3.internal.HTTP3ErrorCode; import org.eclipse.jetty.http3.qpack.QpackDecoder; import org.eclipse.jetty.util.BufferUtil; @@ -128,8 +129,9 @@ public Result parse(ByteBuffer buffer) return Result.NO_FRAME; } + // SPEC: grease and unknown frame types are ignored. if (LOG.isDebugEnabled()) - LOG.debug("ignoring unknown frame type {}", Long.toHexString(frameType)); + LOG.debug("ignoring {} frame type {}", Grease.isGreaseValue(frameType) ? "grease" : "unknown", Long.toHexString(frameType)); BodyParser.Result result = unknownBodyParser.parse(buffer); if (result == BodyParser.Result.NO_FRAME) diff --git a/jetty-http3/http3-server/src/main/java/org/eclipse/jetty/http3/server/internal/ServerHTTP3Session.java b/jetty-http3/http3-server/src/main/java/org/eclipse/jetty/http3/server/internal/ServerHTTP3Session.java index 152759d9c109..b3e7b1a781c7 100644 --- a/jetty-http3/http3-server/src/main/java/org/eclipse/jetty/http3/server/internal/ServerHTTP3Session.java +++ b/jetty-http3/http3-server/src/main/java/org/eclipse/jetty/http3/server/internal/ServerHTTP3Session.java @@ -24,6 +24,7 @@ import org.eclipse.jetty.http3.internal.ControlFlusher; import org.eclipse.jetty.http3.internal.DecoderStreamConnection; import org.eclipse.jetty.http3.internal.EncoderStreamConnection; +import org.eclipse.jetty.http3.internal.Grease; import org.eclipse.jetty.http3.internal.HTTP3ErrorCode; import org.eclipse.jetty.http3.internal.InstructionFlusher; import org.eclipse.jetty.http3.internal.InstructionHandler; @@ -62,7 +63,7 @@ public ServerHTTP3Session(HTTP3Configuration configuration, ServerQuicSession qu if (LOG.isDebugEnabled()) LOG.debug("initializing HTTP/3 streams"); - long encoderStreamId = getQuicSession().newStreamId(StreamType.SERVER_UNIDIRECTIONAL); + long encoderStreamId = newStreamId(StreamType.SERVER_UNIDIRECTIONAL); QuicStreamEndPoint encoderEndPoint = openInstructionEndPoint(encoderStreamId); InstructionFlusher encoderInstructionFlusher = new InstructionFlusher(quicSession, encoderEndPoint, EncoderStreamConnection.STREAM_TYPE); encoder = new QpackEncoder(new InstructionHandler(encoderInstructionFlusher)); @@ -71,7 +72,7 @@ public ServerHTTP3Session(HTTP3Configuration configuration, ServerQuicSession qu if (LOG.isDebugEnabled()) LOG.debug("created encoder stream #{} on {}", encoderStreamId, encoderEndPoint); - long decoderStreamId = getQuicSession().newStreamId(StreamType.SERVER_UNIDIRECTIONAL); + long decoderStreamId = newStreamId(StreamType.SERVER_UNIDIRECTIONAL); QuicStreamEndPoint decoderEndPoint = openInstructionEndPoint(decoderStreamId); InstructionFlusher decoderInstructionFlusher = new InstructionFlusher(quicSession, decoderEndPoint, DecoderStreamConnection.STREAM_TYPE); decoder = new QpackDecoder(new InstructionHandler(decoderInstructionFlusher)); @@ -79,7 +80,7 @@ public ServerHTTP3Session(HTTP3Configuration configuration, ServerQuicSession qu if (LOG.isDebugEnabled()) LOG.debug("created decoder stream #{} on {}", decoderStreamId, decoderEndPoint); - long controlStreamId = getQuicSession().newStreamId(StreamType.SERVER_UNIDIRECTIONAL); + long controlStreamId = newStreamId(StreamType.SERVER_UNIDIRECTIONAL); QuicStreamEndPoint controlEndPoint = openControlEndPoint(controlStreamId); controlFlusher = new ControlFlusher(quicSession, controlEndPoint, configuration.isUseOutputDirectByteBuffers()); addBean(controlFlusher); @@ -105,6 +106,11 @@ public HTTP3SessionServer getSessionServer() return session; } + public long newStreamId(StreamType streamType) + { + return getQuicSession().newStreamId(streamType); + } + @Override protected void onStart() { @@ -170,21 +176,27 @@ public void onSettings(SettingsFrame frame) { if (key == SettingsFrame.MAX_TABLE_CAPACITY) { - int maxTableCapacity = value.intValue(); + int maxTableCapacity = (int)Math.min(value, Integer.MAX_VALUE); encoder.setMaxTableCapacity(maxTableCapacity); encoder.setTableCapacity(Math.min(maxTableCapacity, configuration.getMaxEncoderTableCapacity())); } else if (key == SettingsFrame.MAX_FIELD_SECTION_SIZE) { // Must cap the maxHeaderSize to avoid large allocations. - int maxHeadersSize = Math.min(value.intValue(), configuration.getMaxResponseHeadersSize()); + int maxHeadersSize = (int)Math.min(value, configuration.getMaxResponseHeadersSize()); encoder.setMaxHeadersSize(maxHeadersSize); } else if (key == SettingsFrame.MAX_BLOCKED_STREAMS) { - int maxBlockedStreams = value.intValue(); + int maxBlockedStreams = (int)Math.min(value, Integer.MAX_VALUE); encoder.setMaxBlockedStreams(maxBlockedStreams); } + else + { + // SPEC: grease and unknown settings are ignored. + if (LOG.isDebugEnabled()) + LOG.debug("ignored {} setting {}={}", Grease.isGreaseValue(key) ? "grease" : "unknown", key, value); + } }); }