Remove dead code and fix warnings in the http2 module (#11593)

Motivation:
Opportunities for clean up found while working on a different PR.

Modification:
* Dead code has been removed.
* Unnecessary parenthesis, qualifiers, etc. removed.
* Unused imports removed.
* Override annotations added where missing.

Result:
Cleaner code
This commit is contained in:
Chris Vest 2021-08-18 20:43:57 +02:00
parent 9eb4f0ee85
commit 4a7fa3777e
39 changed files with 74 additions and 267 deletions

View File

@ -18,7 +18,6 @@ package io.netty.handler.codec.http2;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.handler.codec.http2.Http2HeadersEncoder.SensitivityDetector; import io.netty.handler.codec.http2.Http2HeadersEncoder.SensitivityDetector;
import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.UnstableApi; import io.netty.util.internal.UnstableApi;
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_HEADER_LIST_SIZE; import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_HEADER_LIST_SIZE;
@ -347,7 +346,7 @@ public abstract class AbstractHttp2ConnectionHandlerBuilder<T extends Http2Conne
*/ */
protected B encoderEnforceMaxQueuedControlFrames(int maxQueuedControlFrames) { protected B encoderEnforceMaxQueuedControlFrames(int maxQueuedControlFrames) {
enforceNonCodecConstraints("encoderEnforceMaxQueuedControlFrames"); enforceNonCodecConstraints("encoderEnforceMaxQueuedControlFrames");
this.maxQueuedControlFrames = ObjectUtil.checkPositiveOrZero(maxQueuedControlFrames, "maxQueuedControlFrames"); this.maxQueuedControlFrames = checkPositiveOrZero(maxQueuedControlFrames, "maxQueuedControlFrames");
return self(); return self();
} }
@ -376,7 +375,7 @@ public abstract class AbstractHttp2ConnectionHandlerBuilder<T extends Http2Conne
*/ */
protected B encoderIgnoreMaxHeaderListSize(boolean ignoreMaxHeaderListSize) { protected B encoderIgnoreMaxHeaderListSize(boolean ignoreMaxHeaderListSize) {
enforceNonCodecConstraints("encoderIgnoreMaxHeaderListSize"); enforceNonCodecConstraints("encoderIgnoreMaxHeaderListSize");
this.encoderIgnoreMaxHeaderListSize = ignoreMaxHeaderListSize; encoderIgnoreMaxHeaderListSize = ignoreMaxHeaderListSize;
return self(); return self();
} }
@ -428,7 +427,7 @@ public abstract class AbstractHttp2ConnectionHandlerBuilder<T extends Http2Conne
*/ */
protected B decoderEnforceMaxConsecutiveEmptyDataFrames(int maxConsecutiveEmptyFrames) { protected B decoderEnforceMaxConsecutiveEmptyDataFrames(int maxConsecutiveEmptyFrames) {
enforceNonCodecConstraints("maxConsecutiveEmptyFrames"); enforceNonCodecConstraints("maxConsecutiveEmptyFrames");
this.maxConsecutiveEmptyFrames = ObjectUtil.checkPositiveOrZero( this.maxConsecutiveEmptyFrames = checkPositiveOrZero(
maxConsecutiveEmptyFrames, "maxConsecutiveEmptyFrames"); maxConsecutiveEmptyFrames, "maxConsecutiveEmptyFrames");
return self(); return self();
} }
@ -439,7 +438,7 @@ public abstract class AbstractHttp2ConnectionHandlerBuilder<T extends Http2Conne
*/ */
protected B autoAckSettingsFrame(boolean autoAckSettings) { protected B autoAckSettingsFrame(boolean autoAckSettings) {
enforceNonCodecConstraints("autoAckSettingsFrame"); enforceNonCodecConstraints("autoAckSettingsFrame");
this.autoAckSettingsFrame = autoAckSettings; autoAckSettingsFrame = autoAckSettings;
return self(); return self();
} }

View File

@ -102,7 +102,7 @@ abstract class AbstractHttp2StreamChannel extends DefaultAttributeMap implements
if (cause != null) { if (cause != null) {
Throwable unwrappedCause; Throwable unwrappedCause;
// Unwrap if needed // Unwrap if needed
if (cause instanceof Http2FrameStreamException && ((unwrappedCause = cause.getCause()) != null)) { if (cause instanceof Http2FrameStreamException && (unwrappedCause = cause.getCause()) != null) {
cause = unwrappedCause; cause = unwrappedCause;
} }
@ -656,7 +656,7 @@ abstract class AbstractHttp2StreamChannel extends DefaultAttributeMap implements
// Only ever send a reset frame if the connection is still alive and if the stream was created before // Only ever send a reset frame if the connection is still alive and if the stream was created before
// as otherwise we may send a RST on a stream in an invalid state and cause a connection error. // as otherwise we may send a RST on a stream in an invalid state and cause a connection error.
if (parent().isActive() && !readEOS && Http2CodecUtil.isStreamIdValid(stream.id())) { if (parent().isActive() && !readEOS && isStreamIdValid(stream.id())) {
Http2StreamFrame resetFrame = new DefaultHttp2ResetFrame(Http2Error.CANCEL).stream(stream()); Http2StreamFrame resetFrame = new DefaultHttp2ResetFrame(Http2Error.CANCEL).stream(stream());
write(resetFrame, newPromise()); write(resetFrame, newPromise());
flush(); flush();

View File

@ -45,7 +45,7 @@ public abstract class AbstractHttp2StreamFrame implements Http2StreamFrame {
return false; return false;
} }
Http2StreamFrame other = (Http2StreamFrame) o; Http2StreamFrame other = (Http2StreamFrame) o;
return stream == other.stream() || (stream != null && stream.equals(other.stream())); return stream == other.stream() || stream != null && stream.equals(other.stream());
} }
@Override @Override

View File

@ -675,7 +675,7 @@ public class DefaultHttp2Connection implements Http2Connection {
*/ */
private int nextReservationStreamId; private int nextReservationStreamId;
private int lastStreamKnownByPeer = -1; private int lastStreamKnownByPeer = -1;
private boolean pushToAllowed = true; private boolean pushToAllowed;
private F flowController; private F flowController;
private int maxStreams; private int maxStreams;
private int maxActiveStreams; private int maxActiveStreams;
@ -840,7 +840,7 @@ public class DefaultHttp2Connection implements Http2Connection {
} }
private void lastStreamKnownByPeer(int lastKnownStream) { private void lastStreamKnownByPeer(int lastKnownStream) {
this.lastStreamKnownByPeer = lastKnownStream; lastStreamKnownByPeer = lastKnownStream;
} }
@Override @Override

View File

@ -163,11 +163,6 @@ public class DefaultHttp2ConnectionDecoder implements Http2ConnectionDecoder {
return listener; return listener;
} }
// Visible for testing
Http2FrameListener internalFrameListener() {
return internalFrameListener;
}
@Override @Override
public boolean prefaceReceived() { public boolean prefaceReceived() {
return FrameReadListener.class == internalFrameListener.getClass(); return FrameReadListener.class == internalFrameListener.getClass();
@ -625,7 +620,8 @@ public class DefaultHttp2ConnectionDecoder implements Http2ConnectionDecoder {
// sent). We don't have enough information to know for sure, so we choose the lesser of the two errors. // sent). We don't have enough information to know for sure, so we choose the lesser of the two errors.
throw streamError(streamId, STREAM_CLOSED, "Received %s frame for an unknown stream %d", throw streamError(streamId, STREAM_CLOSED, "Received %s frame for an unknown stream %d",
frameName, streamId); frameName, streamId);
} else if (stream.isResetSent() || streamCreatedAfterGoAwaySent(streamId)) { }
if (stream.isResetSent() || streamCreatedAfterGoAwaySent(streamId)) {
// If we have sent a reset stream it is assumed the stream will be closed after the write completes. // If we have sent a reset stream it is assumed the stream will be closed after the write completes.
// If we have not sent a reset, but the stream was created after a GoAway this is not supported by // If we have not sent a reset, but the stream was created after a GoAway this is not supported by
// DefaultHttp2Connection and if a custom Http2Connection is used it is assumed the lifetime is managed // DefaultHttp2Connection and if a custom Http2Connection is used it is assumed the lifetime is managed
@ -634,8 +630,8 @@ public class DefaultHttp2ConnectionDecoder implements Http2ConnectionDecoder {
if (logger.isInfoEnabled()) { if (logger.isInfoEnabled()) {
logger.info("{} ignoring {} frame for stream {}", ctx.channel(), frameName, logger.info("{} ignoring {} frame for stream {}", ctx.channel(), frameName,
stream.isResetSent() ? "RST_STREAM sent." : stream.isResetSent() ? "RST_STREAM sent." :
("Stream created after GOAWAY sent. Last known stream by peer " + "Stream created after GOAWAY sent. Last known stream by peer " +
connection.remote().lastStreamKnownByPeer())); connection.remote().lastStreamKnownByPeer());
} }
return true; return true;

View File

@ -539,7 +539,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Ht
*/ */
private final class FlowControlledHeaders extends FlowControlledBase { private final class FlowControlledHeaders extends FlowControlledBase {
private final Http2Headers headers; private final Http2Headers headers;
private final boolean hasPriorty; private final boolean hasPriority;
private final int streamDependency; private final int streamDependency;
private final short weight; private final short weight;
private final boolean exclusive; private final boolean exclusive;
@ -549,7 +549,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Ht
int padding, boolean endOfStream, ChannelPromise promise) { int padding, boolean endOfStream, ChannelPromise promise) {
super(stream, padding, endOfStream, promise); super(stream, padding, endOfStream, promise);
this.headers = headers; this.headers = headers;
this.hasPriorty = hasPriority; this.hasPriority = hasPriority;
this.streamDependency = streamDependency; this.streamDependency = streamDependency;
this.weight = weight; this.weight = weight;
this.exclusive = exclusive; this.exclusive = exclusive;
@ -575,7 +575,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Ht
// closeStreamLocal(). // closeStreamLocal().
promise.addListener(this); promise.addListener(this);
ChannelFuture f = sendHeaders(frameWriter, ctx, stream.id(), headers, hasPriorty, streamDependency, ChannelFuture f = sendHeaders(frameWriter, ctx, stream.id(), headers, hasPriority, streamDependency,
weight, exclusive, padding, endOfStream, promise); weight, exclusive, padding, endOfStream, promise);
// Writing headers may fail during the encode state if they violate HPACK limits. // Writing headers may fail during the encode state if they violate HPACK limits.
Throwable failureCause = f.cause(); Throwable failureCause = f.cause();

View File

@ -26,7 +26,6 @@ import static io.netty.handler.codec.http2.Http2CodecUtil.INT_FIELD_LENGTH;
import static io.netty.handler.codec.http2.Http2CodecUtil.PING_FRAME_PAYLOAD_LENGTH; import static io.netty.handler.codec.http2.Http2CodecUtil.PING_FRAME_PAYLOAD_LENGTH;
import static io.netty.handler.codec.http2.Http2CodecUtil.PRIORITY_ENTRY_LENGTH; import static io.netty.handler.codec.http2.Http2CodecUtil.PRIORITY_ENTRY_LENGTH;
import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_INITIAL_WINDOW_SIZE; import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_INITIAL_WINDOW_SIZE;
import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_MAX_FRAME_SIZE;
import static io.netty.handler.codec.http2.Http2CodecUtil.SETTING_ENTRY_LENGTH; import static io.netty.handler.codec.http2.Http2CodecUtil.SETTING_ENTRY_LENGTH;
import static io.netty.handler.codec.http2.Http2CodecUtil.headerListSizeExceeded; import static io.netty.handler.codec.http2.Http2CodecUtil.headerListSizeExceeded;
import static io.netty.handler.codec.http2.Http2CodecUtil.isMaxFrameSizeValid; import static io.netty.handler.codec.http2.Http2CodecUtil.isMaxFrameSizeValid;
@ -519,14 +518,10 @@ public class DefaultHttp2FrameReader implements Http2FrameReader, Http2FrameSize
try { try {
settings.put(id, Long.valueOf(value)); settings.put(id, Long.valueOf(value));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
switch(id) { if (id == SETTINGS_INITIAL_WINDOW_SIZE) {
case SETTINGS_MAX_FRAME_SIZE:
throw connectionError(PROTOCOL_ERROR, e, e.getMessage());
case SETTINGS_INITIAL_WINDOW_SIZE:
throw connectionError(FLOW_CONTROL_ERROR, e, e.getMessage()); throw connectionError(FLOW_CONTROL_ERROR, e, e.getMessage());
default:
throw connectionError(PROTOCOL_ERROR, e, e.getMessage());
} }
throw connectionError(PROTOCOL_ERROR, e, e.getMessage());
} }
} }
listener.onSettingsRead(ctx, settings); listener.onSettingsRead(ctx, settings);

View File

@ -203,7 +203,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter, Http2FrameSize
do { do {
int frameDataBytes = min(remainingData, maxFrameSize); int frameDataBytes = min(remainingData, maxFrameSize);
int framePaddingBytes = min(padding, max(0, (maxFrameSize - 1) - frameDataBytes)); int framePaddingBytes = min(padding, max(0, maxFrameSize - 1 - frameDataBytes));
// Decrement the remaining counters. // Decrement the remaining counters.
padding -= framePaddingBytes; padding -= framePaddingBytes;
@ -623,10 +623,4 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter, Http2FrameSize
private static void verifyWindowSizeIncrement(int windowSizeIncrement) { private static void verifyWindowSizeIncrement(int windowSizeIncrement) {
checkPositiveOrZero(windowSizeIncrement, "windowSizeIncrement"); checkPositiveOrZero(windowSizeIncrement, "windowSizeIncrement");
} }
private static void verifyPingPayload(ByteBuf data) {
if (data == null || data.readableBytes() != PING_FRAME_PAYLOAD_LENGTH) {
throw new IllegalArgumentException("Opaque data must be " + PING_FRAME_PAYLOAD_LENGTH + " bytes");
}
}
} }

View File

@ -166,7 +166,7 @@ public final class DefaultHttp2GoAwayFrame extends DefaultByteBufHolder implemen
@Override @Override
public int hashCode() { public int hashCode() {
int hash = super.hashCode(); int hash = super.hashCode();
hash = hash * 31 + (int) (errorCode ^ (errorCode >>> 32)); hash = hash * 31 + (int) (errorCode ^ errorCode >>> 32);
hash = hash * 31 + extraStreamIds; hash = hash * 31 + extraStreamIds;
return hash; return hash;
} }

View File

@ -184,7 +184,7 @@ public class DefaultHttp2Headers
} }
private final class Http2HeaderEntry extends HeaderEntry<CharSequence, CharSequence> { private final class Http2HeaderEntry extends HeaderEntry<CharSequence, CharSequence> {
protected Http2HeaderEntry(int hash, CharSequence key, CharSequence value, Http2HeaderEntry(int hash, CharSequence key, CharSequence value,
HeaderEntry<CharSequence, CharSequence> next) { HeaderEntry<CharSequence, CharSequence> next) {
super(hash, key); super(hash, key);
this.value = value; this.value = value;

View File

@ -80,7 +80,7 @@ public class DefaultHttp2HeadersDecoder implements Http2HeadersDecoder, Http2Hea
DefaultHttp2HeadersDecoder(boolean validateHeaders, HpackDecoder hpackDecoder) { DefaultHttp2HeadersDecoder(boolean validateHeaders, HpackDecoder hpackDecoder) {
this.hpackDecoder = requireNonNull(hpackDecoder, "hpackDecoder"); this.hpackDecoder = requireNonNull(hpackDecoder, "hpackDecoder");
this.validateHeaders = validateHeaders; this.validateHeaders = validateHeaders;
this.maxHeaderListSizeGoAway = maxHeaderListSizeGoAway =
Http2CodecUtil.calculateMaxHeaderListSizeGoAway(hpackDecoder.getMaxHeaderListSize()); Http2CodecUtil.calculateMaxHeaderListSizeGoAway(hpackDecoder.getMaxHeaderListSize());
} }
@ -101,7 +101,7 @@ public class DefaultHttp2HeadersDecoder implements Http2HeadersDecoder, Http2Hea
goAwayMax, max); goAwayMax, max);
} }
hpackDecoder.setMaxHeaderListSize(max); hpackDecoder.setMaxHeaderListSize(max);
this.maxHeaderListSizeGoAway = goAwayMax; maxHeaderListSizeGoAway = goAwayMax;
} }
@Override @Override

View File

@ -411,7 +411,7 @@ public class DefaultHttp2LocalFlowController implements Http2LocalFlowController
window += delta; window += delta;
processedWindow += delta; processedWindow += delta;
lowerBound = Math.min(delta, 0); lowerBound = min(delta, 0);
} }
@Override @Override

View File

@ -108,7 +108,7 @@ public class DefaultHttp2RemoteFlowController implements Http2RemoteFlowControll
@Override @Override
public void onStreamHalfClosed(Http2Stream stream) { public void onStreamHalfClosed(Http2Stream stream) {
if (HALF_CLOSED_LOCAL == stream.state()) { if (HALF_CLOSED_LOCAL == stream.state()) {
/** /*
* When this method is called there should not be any * When this method is called there should not be any
* pending frames left if the API is used correctly. However, * pending frames left if the API is used correctly. However,
* it is possible that a erroneous application can sneak * it is possible that a erroneous application can sneak

View File

@ -79,7 +79,7 @@ public final class DefaultHttp2ResetFrame extends AbstractHttp2StreamFrame imple
@Override @Override
public int hashCode() { public int hashCode() {
int hash = super.hashCode(); int hash = super.hashCode();
hash = hash * 31 + (int) (errorCode ^ (errorCode >>> 32)); hash = hash * 31 + (int) (errorCode ^ errorCode >>> 32);
return hash; return hash;
} }
} }

View File

@ -189,7 +189,7 @@ final class HpackDecoder {
} }
} else { } else {
// Literal Header Field without Indexing / never Indexed // Literal Header Field without Indexing / never Indexed
indexType = ((b & 0x10) == 0x10) ? IndexType.NEVER : IndexType.NONE; indexType = (b & 0x10) == 0x10 ? IndexType.NEVER : IndexType.NONE;
index = b & 0x0F; index = b & 0x0F;
switch (index) { switch (index) {
case 0: case 0:
@ -560,7 +560,7 @@ final class HpackDecoder {
if (validate) { if (validate) {
try { try {
previousType = HpackDecoder.validate(streamId, name, previousType); previousType = validate(streamId, name, previousType);
} catch (Http2Exception ex) { } catch (Http2Exception ex) {
validationException = ex; validationException = ex;
return; return;

View File

@ -245,14 +245,14 @@ final class HpackEncoder {
*/ */
private static void encodeInteger(ByteBuf out, int mask, int n, long i) { private static void encodeInteger(ByteBuf out, int mask, int n, long i) {
assert n >= 0 && n <= 8 : "N: " + n; assert n >= 0 && n <= 8 : "N: " + n;
int nbits = 0xFF >>> (8 - n); int nbits = 0xFF >>> 8 - n;
if (i < nbits) { if (i < nbits) {
out.writeByte((int) (mask | i)); out.writeByte((int) (mask | i));
} else { } else {
out.writeByte(mask | nbits); out.writeByte(mask | nbits);
long length = i - nbits; long length = i - nbits;
for (; (length & ~0x7F) != 0; length >>>= 7) { for (; (length & ~0x7F) != 0; length >>>= 7) {
out.writeByte((int) ((length & 0x7F) | 0x80)); out.writeByte((int) (length & 0x7F | 0x80));
} }
out.writeByte((int) length); out.writeByte((int) length);
} }

View File

@ -199,7 +199,7 @@ final class HpackStaticTable {
/** /**
* Returns the last position in the array that contains multiple * Returns the last position in the array that contains multiple
* fields with the same name. Starting from this position, all * fields with the same name. Starting from this position, all
* names are unique. Similary to {@link getIndexInsensitive} method * names are unique. Similary to {@link #getIndexInsensitive(CharSequence, CharSequence)} method
* assumes all entries for a given header field are sequential * assumes all entries for a given header field are sequential
*/ */
private static int maxSameNameFieldIndex() { private static int maxSameNameFieldIndex() {

View File

@ -89,7 +89,7 @@ public interface Http2Connection {
/** /**
* Called when a {@code GOAWAY} was received from the remote endpoint. This event handler duplicates {@link * Called when a {@code GOAWAY} was received from the remote endpoint. This event handler duplicates {@link
* Http2FrameListener#onGoAwayRead(io.netty.channel.ChannelHandlerContext, int, long, io.netty.buffer.ByteBuf)} * Http2FrameListener#onGoAwayRead(io.netty.channel.ChannelHandlerContext, int, long, ByteBuf)}
* but is added here in order to simplify application logic for handling {@code GOAWAY} in a uniform way. An * but is added here in order to simplify application logic for handling {@code GOAWAY} in a uniform way. An
* application should generally not handle both events, but if it does this method is called second, after * application should generally not handle both events, but if it does this method is called second, after
* notifying the {@link Http2FrameListener}. * notifying the {@link Http2FrameListener}.

View File

@ -40,7 +40,7 @@ public enum Http2Error {
private final long code; private final long code;
private static final Http2Error[] INT_TO_ENUM_MAP; private static final Http2Error[] INT_TO_ENUM_MAP;
static { static {
Http2Error[] errors = Http2Error.values(); Http2Error[] errors = values();
Http2Error[] map = new Http2Error[errors.length]; Http2Error[] map = new Http2Error[errors.length];
for (Http2Error error : errors) { for (Http2Error error : errors) {
map[(int) error.code()] = error; map[(int) error.code()] = error;

View File

@ -127,25 +127,25 @@ public class Http2Exception extends Exception {
/** /**
* Use if an error which can be isolated to a single stream has occurred. If the {@code id} is not * Use if an error which can be isolated to a single stream has occurred. If the {@code id} is not
* {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a {@link Http2Exception.StreamException} will be returned. * {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a {@link StreamException} will be returned.
* Otherwise the error is considered a connection error and a {@link Http2Exception} is returned. * Otherwise the error is considered a connection error and a {@link Http2Exception} is returned.
* @param id The stream id for which the error is isolated to. * @param id The stream id for which the error is isolated to.
* @param error The type of error as defined by the HTTP/2 specification. * @param error The type of error as defined by the HTTP/2 specification.
* @param fmt String with the content and format for the additional debug data. * @param fmt String with the content and format for the additional debug data.
* @param args Objects which fit into the format defined by {@code fmt}. * @param args Objects which fit into the format defined by {@code fmt}.
* @return If the {@code id} is not * @return If the {@code id} is not
* {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a {@link Http2Exception.StreamException} will be returned. * {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a {@link StreamException} will be returned.
* Otherwise the error is considered a connection error and a {@link Http2Exception} is returned. * Otherwise the error is considered a connection error and a {@link Http2Exception} is returned.
*/ */
public static Http2Exception streamError(int id, Http2Error error, String fmt, Object... args) { public static Http2Exception streamError(int id, Http2Error error, String fmt, Object... args) {
return CONNECTION_STREAM_ID == id ? return CONNECTION_STREAM_ID == id ?
Http2Exception.connectionError(error, fmt, args) : connectionError(error, fmt, args) :
new StreamException(id, error, String.format(fmt, args)); new StreamException(id, error, String.format(fmt, args));
} }
/** /**
* Use if an error which can be isolated to a single stream has occurred. If the {@code id} is not * Use if an error which can be isolated to a single stream has occurred. If the {@code id} is not
* {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a {@link Http2Exception.StreamException} will be returned. * {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a {@link StreamException} will be returned.
* Otherwise the error is considered a connection error and a {@link Http2Exception} is returned. * Otherwise the error is considered a connection error and a {@link Http2Exception} is returned.
* @param id The stream id for which the error is isolated to. * @param id The stream id for which the error is isolated to.
* @param error The type of error as defined by the HTTP/2 specification. * @param error The type of error as defined by the HTTP/2 specification.
@ -153,20 +153,20 @@ public class Http2Exception extends Exception {
* @param fmt String with the content and format for the additional debug data. * @param fmt String with the content and format for the additional debug data.
* @param args Objects which fit into the format defined by {@code fmt}. * @param args Objects which fit into the format defined by {@code fmt}.
* @return If the {@code id} is not * @return If the {@code id} is not
* {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a {@link Http2Exception.StreamException} will be returned. * {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a {@link StreamException} will be returned.
* Otherwise the error is considered a connection error and a {@link Http2Exception} is returned. * Otherwise the error is considered a connection error and a {@link Http2Exception} is returned.
*/ */
public static Http2Exception streamError(int id, Http2Error error, Throwable cause, public static Http2Exception streamError(int id, Http2Error error, Throwable cause,
String fmt, Object... args) { String fmt, Object... args) {
return CONNECTION_STREAM_ID == id ? return CONNECTION_STREAM_ID == id ?
Http2Exception.connectionError(error, cause, fmt, args) : connectionError(error, cause, fmt, args) :
new StreamException(id, error, String.format(fmt, args), cause); new StreamException(id, error, String.format(fmt, args), cause);
} }
/** /**
* A specific stream error resulting from failing to decode headers that exceeds the max header size list. * A specific stream error resulting from failing to decode headers that exceeds the max header size list.
* If the {@code id} is not {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a * If the {@code id} is not {@link Http2CodecUtil#CONNECTION_STREAM_ID} then a
* {@link Http2Exception.StreamException} will be returned. Otherwise the error is considered a * {@link StreamException} will be returned. Otherwise the error is considered a
* connection error and a {@link Http2Exception} is returned. * connection error and a {@link Http2Exception} is returned.
* @param id The stream id for which the error is isolated to. * @param id The stream id for which the error is isolated to.
* @param error The type of error as defined by the HTTP/2 specification. * @param error The type of error as defined by the HTTP/2 specification.
@ -181,14 +181,14 @@ public class Http2Exception extends Exception {
public static Http2Exception headerListSizeError(int id, Http2Error error, boolean onDecode, public static Http2Exception headerListSizeError(int id, Http2Error error, boolean onDecode,
String fmt, Object... args) { String fmt, Object... args) {
return CONNECTION_STREAM_ID == id ? return CONNECTION_STREAM_ID == id ?
Http2Exception.connectionError(error, fmt, args) : connectionError(error, fmt, args) :
new HeaderListSizeException(id, error, String.format(fmt, args), onDecode); new HeaderListSizeException(id, error, String.format(fmt, args), onDecode);
} }
/** /**
* Check if an exception is isolated to a single stream or the entire connection. * Check if an exception is isolated to a single stream or the entire connection.
* @param e The exception to check. * @param e The exception to check.
* @return {@code true} if {@code e} is an instance of {@link Http2Exception.StreamException}. * @return {@code true} if {@code e} is an instance of {@link StreamException}.
* {@code false} otherwise. * {@code false} otherwise.
*/ */
public static boolean isStreamError(Http2Exception e) { public static boolean isStreamError(Http2Exception e) {

View File

@ -71,7 +71,7 @@ public interface Http2Headers extends Headers<CharSequence, CharSequence, Http2H
private static final CharSequenceMap<PseudoHeaderName> PSEUDO_HEADERS = new CharSequenceMap<>(); private static final CharSequenceMap<PseudoHeaderName> PSEUDO_HEADERS = new CharSequenceMap<>();
static { static {
for (PseudoHeaderName pseudoHeader : PseudoHeaderName.values()) { for (PseudoHeaderName pseudoHeader : values()) {
PSEUDO_HEADERS.add(pseudoHeader.value(), pseudoHeader); PSEUDO_HEADERS.add(pseudoHeader.value(), pseudoHeader);
} }
} }

View File

@ -43,7 +43,7 @@ public class Http2MultiplexCodecBuilder
} }
private static ChannelHandler checkSharable(ChannelHandler handler) { private static ChannelHandler checkSharable(ChannelHandler handler) {
if ((handler instanceof ChannelHandlerAdapter && !((ChannelHandlerAdapter) handler).isSharable()) && if (handler instanceof ChannelHandlerAdapter && !((ChannelHandlerAdapter) handler).isSharable() &&
!handler.getClass().isAnnotationPresent(ChannelHandler.Sharable.class)) { !handler.getClass().isAnnotationPresent(ChannelHandler.Sharable.class)) {
throw new IllegalArgumentException("The handler must be Sharable"); throw new IllegalArgumentException("The handler must be Sharable");
} }
@ -77,7 +77,7 @@ public class Http2MultiplexCodecBuilder
} }
public Http2MultiplexCodecBuilder withUpgradeStreamHandler(ChannelHandler upgradeStreamHandler) { public Http2MultiplexCodecBuilder withUpgradeStreamHandler(ChannelHandler upgradeStreamHandler) {
if (this.isServer()) { if (isServer()) {
throw new IllegalArgumentException("Server codecs don't use an extra handler for the upgrade stream"); throw new IllegalArgumentException("Server codecs don't use an extra handler for the upgrade stream");
} }
this.upgradeStreamHandler = upgradeStreamHandler; this.upgradeStreamHandler = upgradeStreamHandler;

View File

@ -64,7 +64,6 @@ public final class Http2StreamChannelBootstrap {
* Allow to specify a {@link ChannelOption} which is used for the {@link Http2StreamChannel} instances once they got * Allow to specify a {@link ChannelOption} which is used for the {@link Http2StreamChannel} instances once they got
* created. Use a value of {@code null} to remove a previous set {@link ChannelOption}. * created. Use a value of {@code null} to remove a previous set {@link ChannelOption}.
*/ */
@SuppressWarnings("unchecked")
public <T> Http2StreamChannelBootstrap option(ChannelOption<T> option, T value) { public <T> Http2StreamChannelBootstrap option(ChannelOption<T> option, T value) {
requireNonNull(option, "option"); requireNonNull(option, "option");
@ -82,7 +81,6 @@ public final class Http2StreamChannelBootstrap {
* Allow to specify an initial attribute of the newly created {@link Http2StreamChannel}. If the {@code value} is * Allow to specify an initial attribute of the newly created {@link Http2StreamChannel}. If the {@code value} is
* {@code null}, the attribute of the specified {@code key} is removed. * {@code null}, the attribute of the specified {@code key} is removed.
*/ */
@SuppressWarnings("unchecked")
public <T> Http2StreamChannelBootstrap attr(AttributeKey<T> key, T value) { public <T> Http2StreamChannelBootstrap attr(AttributeKey<T> key, T value) {
requireNonNull(key, "key"); requireNonNull(key, "key");
if (value == null) { if (value == null) {
@ -113,7 +111,6 @@ public final class Http2StreamChannelBootstrap {
* Open a new {@link Http2StreamChannel} to use and notifies the given {@link Promise}. * Open a new {@link Http2StreamChannel} to use and notifies the given {@link Promise}.
* @return the {@link Future} that will be notified once the channel was opened successfully or it failed. * @return the {@link Future} that will be notified once the channel was opened successfully or it failed.
*/ */
@SuppressWarnings("deprecation")
public Future<Http2StreamChannel> open(final Promise<Http2StreamChannel> promise) { public Future<Http2StreamChannel> open(final Promise<Http2StreamChannel> promise) {
try { try {
ChannelHandlerContext ctx = findCtx(); ChannelHandlerContext ctx = findCtx();
@ -136,9 +133,10 @@ public final class Http2StreamChannelBootstrap {
return promise; return promise;
} }
@SuppressWarnings("deprecation")
private ChannelHandlerContext findCtx() throws ClosedChannelException { private ChannelHandlerContext findCtx() throws ClosedChannelException {
// First try to use cached context and if this not work lets try to lookup the context. // First try to use cached context and if this not work lets try to lookup the context.
ChannelHandlerContext ctx = this.multiplexCtx; ChannelHandlerContext ctx = multiplexCtx;
if (ctx != null && !ctx.isRemoved()) { if (ctx != null && !ctx.isRemoved()) {
return ctx; return ctx;
} }
@ -156,7 +154,7 @@ public final class Http2StreamChannelBootstrap {
throw new ClosedChannelException(); throw new ClosedChannelException();
} }
} }
this.multiplexCtx = ctx; multiplexCtx = ctx;
return ctx; return ctx;
} }

View File

@ -78,7 +78,7 @@ public class Http2StreamFrameToHttpObjectCodec extends MessageToMessageCodec<Htt
@Override @Override
public boolean acceptInboundMessage(Object msg) throws Exception { public boolean acceptInboundMessage(Object msg) throws Exception {
return (msg instanceof Http2HeadersFrame) || (msg instanceof Http2DataFrame); return msg instanceof Http2HeadersFrame || msg instanceof Http2DataFrame;
} }
@Override @Override

View File

@ -443,7 +443,7 @@ public final class HttpConversionUtil {
if (!isOriginForm(requestTargetUri) && !isAsteriskForm(requestTargetUri)) { if (!isOriginForm(requestTargetUri) && !isAsteriskForm(requestTargetUri)) {
// Attempt to take from HOST header before taking from the request-line // Attempt to take from HOST header before taking from the request-line
String host = inHeaders.getAsString(HttpHeaderNames.HOST); String host = inHeaders.getAsString(HttpHeaderNames.HOST);
setHttp2Authority((host == null || host.isEmpty()) ? requestTargetUri.getAuthority() : host, out); setHttp2Authority(host == null || host.isEmpty() ? requestTargetUri.getAuthority() : host, out);
} }
} else if (in instanceof HttpResponse) { } else if (in instanceof HttpResponse) {
HttpResponse response = (HttpResponse) in; HttpResponse response = (HttpResponse) in;

View File

@ -485,7 +485,7 @@ public final class ReadOnlyHttp2Headers implements Http2Headers {
@Override @Override
public int size() { public int size() {
return (pseudoHeaders.length + otherHeaders.length) >>> 1; return pseudoHeaders.length + otherHeaders.length >>> 1;
} }
@Override @Override

View File

@ -126,7 +126,7 @@ public class StreamBufferingEncoder extends DecoratingHttp2ConnectionEncoder {
public StreamBufferingEncoder(Http2ConnectionEncoder delegate, int initialMaxConcurrentStreams) { public StreamBufferingEncoder(Http2ConnectionEncoder delegate, int initialMaxConcurrentStreams) {
super(delegate); super(delegate);
this.maxConcurrentStreams = initialMaxConcurrentStreams; maxConcurrentStreams = initialMaxConcurrentStreams;
connection().addListener(new Http2ConnectionAdapter() { connection().addListener(new Http2ConnectionAdapter() {
@Override @Override

View File

@ -159,7 +159,7 @@ public final class UniformStreamByteDistributor implements StreamByteDistributor
// we gave the state a chance to write zero length frames. We wait until updateStreamableBytes is // we gave the state a chance to write zero length frames. We wait until updateStreamableBytes is
// called again before this state is allowed to write. // called again before this state is allowed to write.
windowNegative = windowSize < 0; windowNegative = windowSize < 0;
if (hasFrame && (windowSize > 0 || (windowSize == 0 && !writing))) { if (hasFrame && (windowSize > 0 || windowSize == 0 && !writing)) {
addToQueue(); addToQueue();
} }
} }

View File

@ -233,7 +233,7 @@ public final class WeightedFairQueueByteDistributor implements StreamByteDistrib
} }
state.weight = weight; state.weight = weight;
if (newParent != state.parent || (exclusive && newParent.children.size() != 1)) { if (newParent != state.parent || exclusive && newParent.children.size() != 1) {
final List<ParentChangedEvent> events; final List<ParentChangedEvent> events;
if (newParent.isDescendantOf(state)) { if (newParent.isDescendantOf(state)) {
events = new ArrayList<>(2 + (exclusive ? newParent.children.size() : 0)); events = new ArrayList<>(2 + (exclusive ? newParent.children.size() : 0));
@ -320,7 +320,7 @@ public final class WeightedFairQueueByteDistributor implements StreamByteDistrib
try { try {
assert nextChildState == null || nextChildState.pseudoTimeToWrite >= childState.pseudoTimeToWrite : assert nextChildState == null || nextChildState.pseudoTimeToWrite >= childState.pseudoTimeToWrite :
"nextChildState[" + nextChildState.streamId + "].pseudoTime(" + nextChildState.pseudoTimeToWrite + "nextChildState[" + nextChildState.streamId + "].pseudoTime(" + nextChildState.pseudoTimeToWrite +
") < " + " childState[" + childState.streamId + "].pseudoTime(" + childState.pseudoTimeToWrite + ")"; ") < " + " childState[" + childState.streamId + "].pseudoTime(" + childState.pseudoTimeToWrite + ')';
int nsent = distribute(nextChildState == null ? maxBytes : int nsent = distribute(nextChildState == null ? maxBytes :
min(maxBytes, (int) min((nextChildState.pseudoTimeToWrite - childState.pseudoTimeToWrite) * min(maxBytes, (int) min((nextChildState.pseudoTimeToWrite - childState.pseudoTimeToWrite) *
childState.weight / oldTotalQueuedWeights + allocationQuantum, MAX_VALUE) childState.weight / oldTotalQueuedWeights + allocationQuantum, MAX_VALUE)
@ -396,9 +396,6 @@ public final class WeightedFairQueueByteDistributor implements StreamByteDistrib
static final StateOnlyComparator INSTANCE = new StateOnlyComparator(); static final StateOnlyComparator INSTANCE = new StateOnlyComparator();
private StateOnlyComparator() {
}
@Override @Override
public int compare(State o1, State o2) { public int compare(State o1, State o2) {
// "priority only streams" (which have not been activated) are higher priority than streams used for data. // "priority only streams" (which have not been activated) are higher priority than streams used for data.
@ -425,9 +422,6 @@ public final class WeightedFairQueueByteDistributor implements StreamByteDistrib
static final StatePseudoTimeComparator INSTANCE = new StatePseudoTimeComparator(); static final StatePseudoTimeComparator INSTANCE = new StatePseudoTimeComparator();
private StatePseudoTimeComparator() {
}
@Override @Override
public int compare(State o1, State o2) { public int compare(State o1, State o2) {
return Long.compare(o1.pseudoTimeToWrite, o2.pseudoTimeToWrite); return Long.compare(o1.pseudoTimeToWrite, o2.pseudoTimeToWrite);
@ -556,7 +550,7 @@ public final class WeightedFairQueueByteDistributor implements StreamByteDistrib
do { do {
// Redistribute the weight of child to its dependency proportionally. // Redistribute the weight of child to its dependency proportionally.
State dependency = itr.next().value(); State dependency = itr.next().value();
dependency.weight = (short) Math.max(1, dependency.weight * child.weight / totalWeight); dependency.weight = (short) max(1, dependency.weight * child.weight / totalWeight);
takeChild(itr, dependency, false, events); takeChild(itr, dependency, false, events);
} while (itr.hasNext()); } while (itr.hasNext());
} }

View File

@ -468,6 +468,7 @@ public class DefaultHttp2ConnectionDecoderTest {
} }
} }
@Test
public void headersReadForUnknownStreamShouldThrow() throws Exception { public void headersReadForUnknownStreamShouldThrow() throws Exception {
when(connection.stream(STREAM_ID)).thenReturn(null); when(connection.stream(STREAM_ID)).thenReturn(null);
assertThrows(Http2Exception.class, new Executable() { assertThrows(Http2Exception.class, new Executable() {
@ -612,7 +613,7 @@ public class DefaultHttp2ConnectionDecoderTest {
} }
} }
@Test() @Test
public void headersReadForPromisedStreamShouldCloseStream() throws Exception { public void headersReadForPromisedStreamShouldCloseStream() throws Exception {
when(stream.state()).thenReturn(RESERVED_REMOTE); when(stream.state()).thenReturn(RESERVED_REMOTE);
decode().onHeadersRead(ctx, STREAM_ID, EmptyHttp2Headers.INSTANCE, 0, true); decode().onHeadersRead(ctx, STREAM_ID, EmptyHttp2Headers.INSTANCE, 0, true);

View File

@ -107,19 +107,19 @@ public class DefaultHttp2ConnectionTest {
} }
@Test @Test
public void removeAllStreamsWithJustOneLocalStream() throws InterruptedException, Http2Exception { public void removeAllStreamsWithJustOneLocalStream() throws Exception {
client.local().createStream(3, false); client.local().createStream(3, false);
testRemoveAllStreams(); testRemoveAllStreams();
} }
@Test @Test
public void removeAllStreamsWithJustOneRemoveStream() throws InterruptedException, Http2Exception { public void removeAllStreamsWithJustOneRemoveStream() throws Exception {
client.remote().createStream(2, false); client.remote().createStream(2, false);
testRemoveAllStreams(); testRemoveAllStreams();
} }
@Test @Test
public void removeAllStreamsWithManyActiveStreams() throws InterruptedException, Http2Exception { public void removeAllStreamsWithManyActiveStreams() throws Exception {
Endpoint<Http2RemoteFlowController> remote = client.remote(); Endpoint<Http2RemoteFlowController> remote = client.remote();
Endpoint<Http2LocalFlowController> local = client.local(); Endpoint<Http2LocalFlowController> local = client.local();
for (int c = 3, s = 2; c < 5000; c += 2, s += 2) { for (int c = 3, s = 2; c < 5000; c += 2, s += 2) {
@ -130,7 +130,7 @@ public class DefaultHttp2ConnectionTest {
} }
@Test @Test
public void removeIndividualStreamsWhileCloseDoesNotNPE() throws InterruptedException, Http2Exception { public void removeIndividualStreamsWhileCloseDoesNotNPE() throws Exception {
final Http2Stream streamA = client.local().createStream(3, false); final Http2Stream streamA = client.local().createStream(3, false);
final Http2Stream streamB = client.remote().createStream(2, false); final Http2Stream streamB = client.remote().createStream(2, false);
doAnswer((Answer<Void>) invocation -> { doAnswer((Answer<Void>) invocation -> {
@ -147,7 +147,7 @@ public class DefaultHttp2ConnectionTest {
} }
@Test @Test
public void removeAllStreamsWhileIteratingActiveStreams() throws InterruptedException, Http2Exception { public void removeAllStreamsWhileIteratingActiveStreams() throws Exception {
final Endpoint<Http2RemoteFlowController> remote = client.remote(); final Endpoint<Http2RemoteFlowController> remote = client.remote();
final Endpoint<Http2LocalFlowController> local = client.local(); final Endpoint<Http2LocalFlowController> local = client.local();
for (int c = 3, s = 2; c < 5000; c += 2, s += 2) { for (int c = 3, s = 2; c < 5000; c += 2, s += 2) {
@ -168,7 +168,7 @@ public class DefaultHttp2ConnectionTest {
@Test @Test
public void removeAllStreamsWhileIteratingActiveStreamsAndExceptionOccurs() public void removeAllStreamsWhileIteratingActiveStreamsAndExceptionOccurs()
throws InterruptedException, Http2Exception { throws Exception {
final Endpoint<Http2RemoteFlowController> remote = client.remote(); final Endpoint<Http2RemoteFlowController> remote = client.remote();
final Endpoint<Http2LocalFlowController> local = client.local(); final Endpoint<Http2LocalFlowController> local = client.local();
for (int c = 3, s = 2; c < 5000; c += 2, s += 2) { for (int c = 3, s = 2; c < 5000; c += 2, s += 2) {

View File

@ -158,7 +158,7 @@ public class DefaultHttp2FrameWriterTest {
} }
/** /**
* Test large headers that exceed {@link DefaultHttp2FrameWriter#maxFrameSize} * Test large headers that exceed {@link DefaultHttp2FrameWriter#maxFrameSize()}
* the remaining headers will be sent in a CONTINUATION frame * the remaining headers will be sent in a CONTINUATION frame
*/ */
@Test @Test

View File

@ -185,7 +185,7 @@ public class DefaultHttp2HeadersTest {
if (entry.getKey().length() == 0 || entry.getKey().charAt(0) != ':') { if (entry.getKey().length() == 0 || entry.getKey().charAt(0) != ':') {
lastNonPseudoName = entry.getKey(); lastNonPseudoName = entry.getKey();
} else if (lastNonPseudoName != null) { } else if (lastNonPseudoName != null) {
fail("All pseudo headers must be fist in iteration. Pseudo header " + entry.getKey() + fail("All pseudo headers must be first in iteration. Pseudo header " + entry.getKey() +
" is after a non pseudo header " + lastNonPseudoName); " is after a non pseudo header " + lastNonPseudoName);
} }
} }

View File

@ -98,7 +98,7 @@ public class HpackDynamicTableTest {
table.add(entry2); table.add(entry2);
assertEquals(2, table.length()); assertEquals(2, table.length());
assertEquals(size1 + size2, table.size()); assertEquals(size1 + size2, table.size());
table.setCapacity((size1 + size2) * 2); //larger capacity table.setCapacity(((long) size1 + size2) * 2); //larger capacity
assertEquals(2, table.length()); assertEquals(2, table.length());
assertEquals(size1 + size2, table.size()); assertEquals(size1 + size2, table.size());
table.setCapacity(size2); //smaller capacity table.setCapacity(size2); //smaller capacity

View File

@ -249,8 +249,8 @@ public class Http2ConnectionHandlerTest {
Http2ConnectionPrefaceAndSettingsFrameWrittenEvent.INSTANCE; Http2ConnectionPrefaceAndSettingsFrameWrittenEvent.INSTANCE;
final AtomicBoolean verified = new AtomicBoolean(false); final AtomicBoolean verified = new AtomicBoolean(false);
final Answer verifier = in -> { final Answer<Object> verifier = in -> {
assertTrue(in.getArgument(0).equals(evt)); // sanity check... assertEquals(in.getArgument(0), evt); // sanity check...
verify(ctx).write(eq(connectionPrefaceBuf())); verify(ctx).write(eq(connectionPrefaceBuf()));
verify(encoder).writeSettings(eq(ctx), any(Http2Settings.class), any(ChannelPromise.class)); verify(encoder).writeSettings(eq(ctx), any(Http2Settings.class), any(ChannelPromise.class));
verified.set(true); verified.set(true);
@ -492,7 +492,7 @@ public class Http2ConnectionHandlerTest {
when(stream.isHeadersSent()).thenReturn(false); when(stream.isHeadersSent()).thenReturn(false);
when(remote.lastStreamCreated()).thenReturn(STREAM_ID); when(remote.lastStreamCreated()).thenReturn(STREAM_ID);
when(frameWriter.writeRstStream(eq(ctx), eq(STREAM_ID), when(frameWriter.writeRstStream(eq(ctx), eq(STREAM_ID),
eq(Http2Error.PROTOCOL_ERROR.code()), eq(promise))).thenReturn(future); eq(PROTOCOL_ERROR.code()), eq(promise))).thenReturn(future);
handler.exceptionCaught(ctx, e); handler.exceptionCaught(ctx, e);
verify(remote).createStream(STREAM_ID, true); verify(remote).createStream(STREAM_ID, true);

View File

@ -44,7 +44,7 @@ final class Http2FrameInboundWriter {
} }
Http2FrameInboundWriter(EmbeddedChannel channel, Http2FrameWriter writer) { Http2FrameInboundWriter(EmbeddedChannel channel, Http2FrameWriter writer) {
this.ctx = new WriteInboundChannelHandlerContext(channel); ctx = new WriteInboundChannelHandlerContext(channel);
this.writer = writer; this.writer = writer;
} }

View File

@ -24,7 +24,6 @@ import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.DefaultChannelPromise; import io.netty.channel.DefaultChannelPromise;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.AsciiString; import io.netty.util.AsciiString;
import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Future;
@ -143,170 +142,6 @@ public final class Http2TestUtil {
private Http2TestUtil() { private Http2TestUtil() {
} }
static class FrameAdapter extends ByteToMessageDecoder {
private final Http2Connection connection;
private final Http2FrameListener listener;
private final DefaultHttp2FrameReader reader;
private final CountDownLatch latch;
FrameAdapter(Http2FrameListener listener, CountDownLatch latch) {
this(null, listener, latch);
}
FrameAdapter(Http2Connection connection, Http2FrameListener listener, CountDownLatch latch) {
this(connection, new DefaultHttp2FrameReader(false), listener, latch);
}
FrameAdapter(Http2Connection connection, DefaultHttp2FrameReader reader, Http2FrameListener listener,
CountDownLatch latch) {
this.connection = connection;
this.listener = listener;
this.reader = reader;
this.latch = latch;
}
private Http2Stream getOrCreateStream(int streamId, boolean halfClosed) throws Http2Exception {
return getOrCreateStream(connection, streamId, halfClosed);
}
public static Http2Stream getOrCreateStream(Http2Connection connection, int streamId, boolean halfClosed)
throws Http2Exception {
if (connection != null) {
Http2Stream stream = connection.stream(streamId);
if (stream == null) {
if (connection.isServer() && streamId % 2 == 0 || !connection.isServer() && streamId % 2 != 0) {
stream = connection.local().createStream(streamId, halfClosed);
} else {
stream = connection.remote().createStream(streamId, halfClosed);
}
}
return stream;
}
return null;
}
private void closeStream(Http2Stream stream) {
closeStream(stream, false);
}
protected void closeStream(Http2Stream stream, boolean dataRead) {
if (stream != null) {
stream.close();
}
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
reader.readFrame(ctx, in, new Http2FrameListener() {
@Override
public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding,
boolean endOfStream) throws Http2Exception {
Http2Stream stream = getOrCreateStream(streamId, endOfStream);
int processed = listener.onDataRead(ctx, streamId, data, padding, endOfStream);
if (endOfStream) {
closeStream(stream, true);
}
latch.countDown();
return processed;
}
@Override
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding,
boolean endStream) throws Http2Exception {
Http2Stream stream = getOrCreateStream(streamId, endStream);
listener.onHeadersRead(ctx, streamId, headers, padding, endStream);
if (endStream) {
closeStream(stream);
}
latch.countDown();
}
@Override
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers,
int streamDependency, short weight, boolean exclusive, int padding, boolean endStream)
throws Http2Exception {
Http2Stream stream = getOrCreateStream(streamId, endStream);
listener.onHeadersRead(ctx, streamId, headers, streamDependency, weight, exclusive, padding,
endStream);
if (endStream) {
closeStream(stream);
}
latch.countDown();
}
@Override
public void onPriorityRead(ChannelHandlerContext ctx, int streamId, int streamDependency, short weight,
boolean exclusive) throws Http2Exception {
listener.onPriorityRead(ctx, streamId, streamDependency, weight, exclusive);
latch.countDown();
}
@Override
public void onRstStreamRead(ChannelHandlerContext ctx, int streamId, long errorCode)
throws Http2Exception {
Http2Stream stream = getOrCreateStream(streamId, false);
listener.onRstStreamRead(ctx, streamId, errorCode);
closeStream(stream);
latch.countDown();
}
@Override
public void onSettingsAckRead(ChannelHandlerContext ctx) throws Http2Exception {
listener.onSettingsAckRead(ctx);
latch.countDown();
}
@Override
public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) throws Http2Exception {
listener.onSettingsRead(ctx, settings);
latch.countDown();
}
@Override
public void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
listener.onPingRead(ctx, data);
latch.countDown();
}
@Override
public void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
listener.onPingAckRead(ctx, data);
latch.countDown();
}
@Override
public void onPushPromiseRead(ChannelHandlerContext ctx, int streamId, int promisedStreamId,
Http2Headers headers, int padding) throws Http2Exception {
getOrCreateStream(promisedStreamId, false);
listener.onPushPromiseRead(ctx, streamId, promisedStreamId, headers, padding);
latch.countDown();
}
@Override
public void onGoAwayRead(ChannelHandlerContext ctx, int lastStreamId, long errorCode, ByteBuf debugData)
throws Http2Exception {
listener.onGoAwayRead(ctx, lastStreamId, errorCode, debugData);
latch.countDown();
}
@Override
public void onWindowUpdateRead(ChannelHandlerContext ctx, int streamId, int windowSizeIncrement)
throws Http2Exception {
getOrCreateStream(streamId, false);
listener.onWindowUpdateRead(ctx, streamId, windowSizeIncrement);
latch.countDown();
}
@Override
public void onUnknownFrame(ChannelHandlerContext ctx, byte frameType, int streamId, Http2Flags flags,
ByteBuf payload) throws Http2Exception {
listener.onUnknownFrame(ctx, frameType, streamId, flags, payload);
latch.countDown();
}
});
}
}
/** /**
* A decorator around a {@link Http2FrameListener} that counts down the latch so that we can await the completion of * A decorator around a {@link Http2FrameListener} that counts down the latch so that we can await the completion of
* the request. * the request.
@ -319,10 +154,6 @@ public final class Http2TestUtil {
private final CountDownLatch trailersLatch; private final CountDownLatch trailersLatch;
private final CountDownLatch goAwayLatch; private final CountDownLatch goAwayLatch;
FrameCountDown(Http2FrameListener listener, CountDownLatch settingsAckLatch, CountDownLatch messageLatch) {
this(listener, settingsAckLatch, messageLatch, null, null);
}
FrameCountDown(Http2FrameListener listener, CountDownLatch settingsAckLatch, CountDownLatch messageLatch, FrameCountDown(Http2FrameListener listener, CountDownLatch settingsAckLatch, CountDownLatch messageLatch,
CountDownLatch dataLatch, CountDownLatch trailersLatch) { CountDownLatch dataLatch, CountDownLatch trailersLatch) {
this(listener, settingsAckLatch, messageLatch, dataLatch, trailersLatch, messageLatch); this(listener, settingsAckLatch, messageLatch, dataLatch, trailersLatch, messageLatch);

View File

@ -145,7 +145,7 @@ public class HttpConversionUtilTest {
@Test @Test
public void stripTEHeadersAccountsForOWS() { public void stripTEHeadersAccountsForOWS() {
HttpHeaders inHeaders = new DefaultHttpHeaders(); HttpHeaders inHeaders = new DefaultHttpHeaders();
inHeaders.add(TE, " " + TRAILERS + " "); inHeaders.add(TE, " " + TRAILERS + ' ');
Http2Headers out = new DefaultHttp2Headers(); Http2Headers out = new DefaultHttp2Headers();
HttpConversionUtil.toHttp2Headers(inHeaders, out); HttpConversionUtil.toHttp2Headers(inHeaders, out);
assertSame(TRAILERS, out.get(TE)); assertSame(TRAILERS, out.get(TE));

View File

@ -244,11 +244,10 @@ public class ReadOnlyHttp2HeadersTest {
@Test @Test
public void testIteratorMultipleValues() { public void testIteratorMultipleValues() {
Http2Headers headers = ReadOnlyHttp2Headers.serverHeaders(false, new AsciiString("200"), new AsciiString[] { Http2Headers headers = ReadOnlyHttp2Headers.serverHeaders(false, new AsciiString("200"),
new AsciiString("name2"), new AsciiString("value1"), new AsciiString("name2"), new AsciiString("value1"),
new AsciiString("name1"), new AsciiString("value2"), new AsciiString("name1"), new AsciiString("value2"),
new AsciiString("name2"), new AsciiString("value3") new AsciiString("name2"), new AsciiString("value3"));
});
Iterator<CharSequence> itr = headers.valueIterator("name2"); Iterator<CharSequence> itr = headers.valueIterator("name2");
assertTrue(itr.hasNext()); assertTrue(itr.hasNext());
assertTrue(AsciiString.contentEqualsIgnoreCase("value1", itr.next())); assertTrue(AsciiString.contentEqualsIgnoreCase("value1", itr.next()));