> inputHeaders)
}
}
- private static Http3Exception streamError(long streamId, Http3ErrorCode error, String msg, Throwable cause) {
+ private static Http3Exception streamError(long streamId, Http3ErrorCode error, String msg,
+ @Nullable Throwable cause) {
return new Http3Exception(error, streamId + ": " + msg, cause);
}
}
diff --git a/src/main/java/io/netty/incubator/codec/http3/NotNullByDefault.java b/src/main/java/io/netty/incubator/codec/http3/NotNullByDefault.java
new file mode 100644
index 0000000..5c33ad9
--- /dev/null
+++ b/src/main/java/io/netty/incubator/codec/http3/NotNullByDefault.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.incubator.codec.http3;
+
+
+import org.jetbrains.annotations.NotNull;
+
+import javax.annotation.meta.TypeQualifierDefault;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies that all parameters and return values of methods within a package should be treated as non-null by
+ * default, unless explicitly annotated with a nullness annotation such as {@link org.jetbrains.annotations.Nullable}.
+ *
+ * This annotation is applied at the package level and affects all types within the annotated package.
+ *
+ * Any nullness annotations explicitly applied to a parameter or return value within a package will override
+ * the default nullness behavior specified by {@link NotNullByDefault}.
+ */
+@Documented
+@TypeQualifierDefault({ ElementType.PARAMETER, ElementType.METHOD })
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.PACKAGE)
+@NotNull
+@interface NotNullByDefault {
+}
diff --git a/src/main/java/io/netty/incubator/codec/http3/QpackEncoderDynamicTable.java b/src/main/java/io/netty/incubator/codec/http3/QpackEncoderDynamicTable.java
index 3ad8103..72ed132 100644
--- a/src/main/java/io/netty/incubator/codec/http3/QpackEncoderDynamicTable.java
+++ b/src/main/java/io/netty/incubator/codec/http3/QpackEncoderDynamicTable.java
@@ -16,6 +16,7 @@
package io.netty.incubator.codec.http3;
import io.netty.util.AsciiString;
+import org.jetbrains.annotations.Nullable;
import static io.netty.incubator.codec.http3.QpackHeaderField.ENTRY_OVERHEAD;
import static io.netty.incubator.codec.http3.QpackUtil.MAX_HEADER_TABLE_SIZE;
@@ -299,7 +300,7 @@ int relativeIndexForEncoderInstructions(int entryIndex) {
* exists, then the index is returned. If an entry with only matching name exists then {@code -index-1} is
* returned.
*/
- int getEntryIndex(CharSequence name, CharSequence value) {
+ int getEntryIndex(@Nullable CharSequence name, @Nullable CharSequence value) {
if (tail != head && name != null && value != null) {
int h = AsciiString.hashCode(name);
int i = index(h);
@@ -334,7 +335,7 @@ int getEntryIndex(CharSequence name, CharSequence value) {
* @return Required
* insert count if the passed entry has to be referenced in a header block.
*/
- int addReferenceToEntry(CharSequence name, CharSequence value, int idx) {
+ int addReferenceToEntry(@Nullable CharSequence name, @Nullable CharSequence value, int idx) {
if (tail != head && name != null && value != null) {
int h = AsciiString.hashCode(name);
int i = index(h);
@@ -466,7 +467,7 @@ private static final class HeaderEntry extends QpackHeaderField {
*/
final int index;
- HeaderEntry(int hash, CharSequence name, CharSequence value, int index, HeaderEntry nextSibling) {
+ HeaderEntry(int hash, CharSequence name, CharSequence value, int index, @Nullable HeaderEntry nextSibling) {
super(name, value);
this.index = index;
this.hash = hash;
diff --git a/src/main/java/io/netty/incubator/codec/http3/QpackEncoderHandler.java b/src/main/java/io/netty/incubator/codec/http3/QpackEncoderHandler.java
index 3f98caa..0cbe31b 100644
--- a/src/main/java/io/netty/incubator/codec/http3/QpackEncoderHandler.java
+++ b/src/main/java/io/netty/incubator/codec/http3/QpackEncoderHandler.java
@@ -21,6 +21,7 @@
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.incubator.codec.quic.QuicStreamChannel;
import io.netty.util.AsciiString;
+import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -36,7 +37,7 @@ final class QpackEncoderHandler extends ByteToMessageDecoder {
private final QpackDecoder qpackDecoder;
private boolean discard;
- QpackEncoderHandler(Long maxTableCapacity, QpackDecoder qpackDecoder) {
+ QpackEncoderHandler(@Nullable Long maxTableCapacity, QpackDecoder qpackDecoder) {
checkInRange(maxTableCapacity == null ? 0 : maxTableCapacity, 0, MAX_UNSIGNED_INT, "maxTableCapacity");
huffmanDecoder = new QpackHuffmanDecoder();
this.qpackDecoder = qpackDecoder;
@@ -222,6 +223,7 @@ private void handleDecodeFailure(ChannelHandlerContext ctx, QpackException cause
connectionError(ctx, new Http3Exception(QPACK_ENCODER_STREAM_ERROR, message, cause), true);
}
+ @Nullable
private CharSequence decodeLiteralValue(ByteBuf in) throws QpackException {
final boolean valueHuffEncoded = QpackUtil.firstByteEquals(in, (byte) 0b1000_0000);
int valueLength = decodePrefixedIntegerAsInt(in, 7);
diff --git a/src/main/java/io/netty/incubator/codec/http3/QpackException.java b/src/main/java/io/netty/incubator/codec/http3/QpackException.java
index 015009f..4138bb6 100644
--- a/src/main/java/io/netty/incubator/codec/http3/QpackException.java
+++ b/src/main/java/io/netty/incubator/codec/http3/QpackException.java
@@ -16,13 +16,15 @@
package io.netty.incubator.codec.http3;
import io.netty.util.internal.ThrowableUtil;
+import org.jetbrains.annotations.Nullable;
/**
* Exception thrown if an error happens during QPACK processing.
*/
public final class QpackException extends Exception {
- private QpackException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ private QpackException(String message, @Nullable Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
diff --git a/src/main/java/io/netty/incubator/codec/http3/package-info.java b/src/main/java/io/netty/incubator/codec/http3/package-info.java
index 59df0a2..2ff7298 100644
--- a/src/main/java/io/netty/incubator/codec/http3/package-info.java
+++ b/src/main/java/io/netty/incubator/codec/http3/package-info.java
@@ -17,4 +17,7 @@
/**
* HTTP/3 implementation.
*/
+
+@NotNullByDefault
package io.netty.incubator.codec.http3;
+
diff --git a/src/test/java/io/netty/incubator/codec/http3/AbstractHttp3FrameTypeValidationHandlerTest.java b/src/test/java/io/netty/incubator/codec/http3/AbstractHttp3FrameTypeValidationHandlerTest.java
index 9e8a183..e763e38 100644
--- a/src/test/java/io/netty/incubator/codec/http3/AbstractHttp3FrameTypeValidationHandlerTest.java
+++ b/src/test/java/io/netty/incubator/codec/http3/AbstractHttp3FrameTypeValidationHandlerTest.java
@@ -37,6 +37,7 @@
import static io.netty.incubator.codec.http3.Http3TestUtils.verifyClose;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
@@ -76,6 +77,7 @@ protected void setUp(boolean server) {
public void tearDown() {
if (parent != null) {
final QpackAttributes qpackAttributes = getQpackAttributes(parent);
+ assertNotNull(qpackAttributes);
if (qpackAttributes.decoderStreamAvailable()) {
assertFalse(((EmbeddedQuicStreamChannel) qpackAttributes.decoderStream()).finish());
}
diff --git a/src/test/java/io/netty/incubator/codec/http3/EmbeddedQuicChannel.java b/src/test/java/io/netty/incubator/codec/http3/EmbeddedQuicChannel.java
index 02aa4ab..93900d5 100644
--- a/src/test/java/io/netty/incubator/codec/http3/EmbeddedQuicChannel.java
+++ b/src/test/java/io/netty/incubator/codec/http3/EmbeddedQuicChannel.java
@@ -40,6 +40,7 @@
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;
+import org.jetbrains.annotations.Nullable;
import javax.net.ssl.SSLEngine;
import java.net.SocketAddress;
@@ -112,6 +113,7 @@ public boolean isTimedOut() {
}
@Override
+ @Nullable
public SSLEngine sslEngine() {
return null;
}
@@ -176,11 +178,13 @@ public Future collectPathStats(int i, Promise {
@@ -97,6 +98,7 @@ public QuicStreamChannel read() {
}
@Override
+ @Nullable
public QuicStreamPriority priority() {
return null;
}
@@ -107,11 +109,13 @@ public ChannelFuture updatePriority(QuicStreamPriority priority, ChannelPromise
}
@Override
+ @Nullable
public QuicStreamAddress localAddress() {
return null;
}
@Override
+ @Nullable
public QuicStreamAddress remoteAddress() {
return null;
}
diff --git a/src/test/java/io/netty/incubator/codec/http3/Http3FrameToHttpObjectCodecTest.java b/src/test/java/io/netty/incubator/codec/http3/Http3FrameToHttpObjectCodecTest.java
index d061f20..1e5e61a 100644
--- a/src/test/java/io/netty/incubator/codec/http3/Http3FrameToHttpObjectCodecTest.java
+++ b/src/test/java/io/netty/incubator/codec/http3/Http3FrameToHttpObjectCodecTest.java
@@ -79,6 +79,7 @@
import java.util.stream.Stream;
import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
@@ -1057,13 +1058,16 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
stream.writeAndFlush(request);
HttpResponse respHeaders = (HttpResponse) received.poll(20, TimeUnit.SECONDS);
+ assertThat(respHeaders, notNullValue());
assertThat(respHeaders.status(), is(HttpResponseStatus.OK));
assertThat(respHeaders, not(instanceOf(LastHttpContent.class)));
HttpContent respBody = (HttpContent) received.poll(20, TimeUnit.SECONDS);
+ assertThat(respBody, notNullValue());
assertThat(respBody.content().toString(CharsetUtil.UTF_8), is("foo"));
respBody.release();
LastHttpContent last = (LastHttpContent) received.poll(20, TimeUnit.SECONDS);
+ assertThat(last, notNullValue());
last.release();
} finally {
group.shutdownGracefully();
diff --git a/src/test/java/io/netty/incubator/codec/http3/Http3RequestStreamValidationHandlerTest.java b/src/test/java/io/netty/incubator/codec/http3/Http3RequestStreamValidationHandlerTest.java
index f5d34ec..f65a378 100644
--- a/src/test/java/io/netty/incubator/codec/http3/Http3RequestStreamValidationHandlerTest.java
+++ b/src/test/java/io/netty/incubator/codec/http3/Http3RequestStreamValidationHandlerTest.java
@@ -25,6 +25,7 @@
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.incubator.codec.quic.QuicStreamChannel;
import io.netty.incubator.codec.quic.QuicStreamType;
+import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
@@ -502,7 +503,7 @@ private void testInformationalResponse(boolean server, boolean expectFail, Http3
assertFalse(channel.finish());
}
- private void testHeadersFrame(Http3HeadersFrame headersFrame, Http3ErrorCode code) throws Exception {
+ private void testHeadersFrame(Http3HeadersFrame headersFrame, @Nullable Http3ErrorCode code) throws Exception {
EmbeddedQuicStreamChannel channel = newServerStream();
try {
assertTrue(channel.writeInbound(headersFrame));
diff --git a/src/test/java/io/netty/incubator/codec/http3/Http3ServerPushStreamManagerTest.java b/src/test/java/io/netty/incubator/codec/http3/Http3ServerPushStreamManagerTest.java
index ab650b4..98d0a8e 100644
--- a/src/test/java/io/netty/incubator/codec/http3/Http3ServerPushStreamManagerTest.java
+++ b/src/test/java/io/netty/incubator/codec/http3/Http3ServerPushStreamManagerTest.java
@@ -24,6 +24,7 @@
import io.netty.incubator.codec.quic.QuicStreamChannel;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.Promise;
+import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -140,7 +141,7 @@ public void pushStreamWithBootstrapWithHandler() throws Exception {
assertTrue(pushStreamHandler.framesWritten.get(0) instanceof Http3HeadersFrame);
}
- private void pushStreamWithBootstrapCreateAndClose(ChannelHandler pushStreamHandler) throws Exception {
+ private void pushStreamWithBootstrapCreateAndClose(@Nullable ChannelHandler pushStreamHandler) throws Exception {
pushStreamCreateAndClose(pushId -> newPushStreamWithBootstrap(pushStreamHandler, pushId));
}
@@ -160,11 +161,13 @@ private void pushStreamCreateAndClose(PushStreamFactory pushStreamFactory) throw
assertFalse(pushStream.isActive());
}
- private EmbeddedQuicStreamChannel newPushStream(ChannelHandler pushStreamHandler, long pushId) throws Exception {
+ private EmbeddedQuicStreamChannel newPushStream(@Nullable ChannelHandler pushStreamHandler,
+ long pushId) throws Exception {
return newPushStream(() -> (EmbeddedQuicStreamChannel) manager.newPushStream(pushId, pushStreamHandler).get());
}
- private EmbeddedQuicStreamChannel newPushStreamWithBootstrap(ChannelHandler pushStreamHandler, long pushId)
+ private EmbeddedQuicStreamChannel newPushStreamWithBootstrap(@Nullable ChannelHandler pushStreamHandler,
+ long pushId)
throws Exception {
return newPushStream(() -> {
final Promise promise = channel.eventLoop().newPromise();
diff --git a/src/test/java/io/netty/incubator/codec/http3/Http3UnidirectionalStreamInboundHandlerTest.java b/src/test/java/io/netty/incubator/codec/http3/Http3UnidirectionalStreamInboundHandlerTest.java
index 9a0456e..543e5b3 100644
--- a/src/test/java/io/netty/incubator/codec/http3/Http3UnidirectionalStreamInboundHandlerTest.java
+++ b/src/test/java/io/netty/incubator/codec/http3/Http3UnidirectionalStreamInboundHandlerTest.java
@@ -25,6 +25,7 @@
import io.netty.incubator.codec.quic.QuicStreamChannel;
import io.netty.incubator.codec.quic.QuicStreamType;
import io.netty.util.ReferenceCountUtil;
+import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -252,7 +253,8 @@ private EmbeddedChannel newChannel(boolean server) throws Exception {
return newChannel(server, null);
}
- private EmbeddedChannel newChannel(boolean server, LongFunction unknownStreamHandlerFactory)
+ private EmbeddedChannel newChannel(boolean server,
+ @Nullable LongFunction unknownStreamHandlerFactory)
throws Exception {
Http3UnidirectionalStreamInboundHandler handler =
newUniStreamInboundHandler(server, unknownStreamHandlerFactory);
@@ -260,7 +262,7 @@ private EmbeddedChannel newChannel(boolean server, LongFunction
}
private Http3UnidirectionalStreamInboundHandler newUniStreamInboundHandler(boolean server,
- LongFunction unknownStreamHandlerFactory) {
+ @Nullable LongFunction unknownStreamHandlerFactory) {
return server ?
new Http3UnidirectionalStreamInboundServerHandler((v, __, ___) -> new CodecHandler(),
localControlStreamHandler, remoteControlStreamHandler, unknownStreamHandlerFactory,
diff --git a/src/test/java/io/netty/incubator/codec/http3/QpackEncoderDecoderTest.java b/src/test/java/io/netty/incubator/codec/http3/QpackEncoderDecoderTest.java
index 734c656..4aeb325 100644
--- a/src/test/java/io/netty/incubator/codec/http3/QpackEncoderDecoderTest.java
+++ b/src/test/java/io/netty/incubator/codec/http3/QpackEncoderDecoderTest.java
@@ -22,6 +22,7 @@
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.util.AsciiString;
+import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -517,7 +518,8 @@ private static final class ForwardWriteToReadOnOtherHandler extends ChannelOutbo
this(other, null);
}
- ForwardWriteToReadOnOtherHandler(ChannelInboundHandler other, BlockingQueue> suspendQueue) {
+ ForwardWriteToReadOnOtherHandler(ChannelInboundHandler other,
+ @Nullable BlockingQueue> suspendQueue) {
this.other = other;
this.suspendQueue = suspendQueue;
}