diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/AbstractHttp2ConnectionHandler.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/AbstractHttp2ConnectionHandler.java index e5f13cbe0b..81f9bbf5e4 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/AbstractHttp2ConnectionHandler.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/AbstractHttp2ConnectionHandler.java @@ -17,7 +17,6 @@ package io.netty.handler.codec.http2; import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_PRIORITY_WEIGHT; import static io.netty.handler.codec.http2.Http2CodecUtil.connectionPrefaceBuf; -import static io.netty.handler.codec.http2.Http2CodecUtil.failAndThrow; import static io.netty.handler.codec.http2.Http2CodecUtil.toByteBuf; import static io.netty.handler.codec.http2.Http2CodecUtil.toHttp2Exception; import static io.netty.handler.codec.http2.Http2Error.NO_ERROR; @@ -189,7 +188,7 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode protected ChannelFuture writeData(final ChannelHandlerContext ctx, final ChannelPromise promise, int streamId, final ByteBuf data, int padding, - boolean endStream, boolean endSegment, boolean compressed) throws Http2Exception { + boolean endStream, boolean endSegment, boolean compressed) { try { if (connection.isGoAway()) { throw protocolError("Sending data after connection going away."); @@ -208,21 +207,19 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode return promise; } catch (Http2Exception e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } protected ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, Http2Headers headers, int padding, boolean endStream, boolean endSegment) - throws Http2Exception { + int streamId, Http2Headers headers, int padding, boolean endStream, boolean endSegment) { return writeHeaders(ctx, promise, streamId, headers, 0, DEFAULT_PRIORITY_WEIGHT, false, padding, endStream, endSegment); } protected ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, Http2Headers headers, int streamDependency, short weight, - boolean exclusive, int padding, boolean endStream, boolean endSegment) - throws Http2Exception { + boolean exclusive, int padding, boolean endStream, boolean endSegment) { try { if (connection.isGoAway()) { throw protocolError("Sending headers after connection going away."); @@ -268,13 +265,12 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode return frameWriter.writeHeaders(ctx, promise, streamId, headers, streamDependency, weight, exclusive, padding, endStream, endSegment); } catch (Http2Exception e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } protected ChannelFuture writePriority(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, int streamDependency, short weight, boolean exclusive) - throws Http2Exception { + int streamId, int streamDependency, short weight, boolean exclusive) { try { if (connection.isGoAway()) { throw protocolError("Sending priority after connection going away."); @@ -286,7 +282,7 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode return frameWriter.writePriority(ctx, promise, streamId, streamDependency, weight, exclusive); } catch (Http2Exception e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } @@ -305,7 +301,7 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode } protected ChannelFuture writeSettings(ChannelHandlerContext ctx, ChannelPromise promise, - Http2Settings settings) throws Http2Exception { + Http2Settings settings) { outstandingLocalSettingsQueue.add(settings); try { if (connection.isGoAway()) { @@ -320,12 +316,12 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode return frameWriter.writeSettings(ctx, promise, settings); } catch (Http2Exception e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } protected ChannelFuture writePing(ChannelHandlerContext ctx, ChannelPromise promise, - ByteBuf data) throws Http2Exception { + ByteBuf data) { try { if (connection.isGoAway()) { throw protocolError("Sending ping after connection going away."); @@ -334,13 +330,12 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode // Just pass the frame through. return frameWriter.writePing(ctx, promise, false, data); } catch (Http2Exception e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } protected ChannelFuture writePushPromise(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, int promisedStreamId, Http2Headers headers, int padding) - throws Http2Exception { + int streamId, int promisedStreamId, Http2Headers headers, int padding) { try { if (connection.isGoAway()) { throw protocolError("Sending push promise after connection going away."); @@ -354,15 +349,14 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode return frameWriter.writePushPromise(ctx, promise, streamId, promisedStreamId, headers, padding); } catch (Http2Exception e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } protected ChannelFuture writeAltSvc(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, long maxAge, int port, ByteBuf protocolId, String host, String origin) - throws Http2Exception { + int streamId, long maxAge, int port, ByteBuf protocolId, String host, String origin) { if (!connection.isServer()) { - throw protocolError("Client sending ALT_SVC frame"); + return promise.setFailure(protocolError("Client sending ALT_SVC frame")); } return frameWriter.writeAltSvc(ctx, promise, streamId, maxAge, port, protocolId, host, origin); @@ -392,7 +386,7 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode * preface strings can only be received by servers, returns true immediately for client * endpoints. */ - private boolean readClientPrefaceString(ChannelHandlerContext ctx, ByteBuf in) throws Http2Exception { + private boolean readClientPrefaceString(ChannelHandlerContext ctx, ByteBuf in) { if (clientPrefaceString == null) { return true; } @@ -918,59 +912,55 @@ public abstract class AbstractHttp2ConnectionHandler extends ByteToMessageDecode @Override public void writeFrame(int streamId, ByteBuf data, int padding, boolean endStream, boolean endSegment, boolean compressed) { - try { - if (promise.isDone()) { - // Most likely the write already failed. Just release the - // buffer. - data.release(); - return; - } - - remaining -= data.readableBytes(); - - // The flow controller may split the write into chunks. Use a new - // promise for intermediate writes. - final ChannelPromise chunkPromise = - remaining == 0 ? promise : ctx.newPromise(); - - // The original promise is already in the list, so don't add again. - if (chunkPromise != promise) { - promises.add(chunkPromise); - } - - // TODO: consider adding a flush() method to this interface. The - // frameWriter flushes on each write which isn't optimal - // for the case of the outbound flow controller, which sends a batch - // of frames when the flow control window changes. We should let - // the flow controller manually flush after all writes are. - // complete. - - // Write the frame. - ChannelFuture future = - frameWriter.writeData(ctx, chunkPromise, streamId, data, - padding, endStream, endSegment, compressed); - - // Close the connection on write failures that leave the outbound - // flow - // control window in a corrupt state. - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) - throws Exception { - if (!future.isSuccess()) { - // If any of the chunk writes fail, also fail the - // original - // future that was returned to the caller. - failAllPromises(future.cause()); - processHttp2Exception(ctx, - toHttp2Exception(future.cause())); - } - } - }); - } catch (Http2Exception e) { - processHttp2Exception(ctx, e); + if (promise.isDone()) { + // Most likely the write already failed. Just release the + // buffer. + data.release(); + return; } + remaining -= data.readableBytes(); + + // The flow controller may split the write into chunks. Use a new + // promise for intermediate writes. + final ChannelPromise chunkPromise = + remaining == 0 ? promise : ctx.newPromise(); + + // The original promise is already in the list, so don't add again. + if (chunkPromise != promise) { + promises.add(chunkPromise); + } + + // TODO: consider adding a flush() method to this interface. The + // frameWriter flushes on each write which isn't optimal + // for the case of the outbound flow controller, which sends a batch + // of frames when the flow control window changes. We should let + // the flow controller manually flush after all writes are. + // complete. + + // Write the frame. + ChannelFuture future = + frameWriter.writeData(ctx, chunkPromise, streamId, data, + padding, endStream, endSegment, compressed); + + // Close the connection on write failures that leave the outbound + // flow + // control window in a corrupt state. + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) + throws Exception { + if (!future.isSuccess()) { + // If any of the chunk writes fail, also fail the + // original + // future that was returned to the caller. + failAllPromises(future.cause()); + processHttp2Exception(ctx, + toHttp2Exception(future.cause())); + } + } + }); + // Close the local side of the stream if this is the last frame if (endStream) { Http2Stream stream = connection.stream(streamId); diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Connection.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Connection.java index 03ac306a22..bd8966a689 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Connection.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Connection.java @@ -22,7 +22,6 @@ import static io.netty.handler.codec.http2.Http2Stream.State.HALF_CLOSED_REMOTE; import static io.netty.handler.codec.http2.Http2Stream.State.OPEN; import static io.netty.handler.codec.http2.Http2Stream.State.RESERVED_LOCAL; import static io.netty.handler.codec.http2.Http2Stream.State.RESERVED_REMOTE; -import io.netty.handler.codec.http2.Http2Stream.State; import java.util.Collections; import java.util.HashMap; @@ -146,10 +145,10 @@ public class DefaultHttp2Connection implements Http2Connection { public Http2Stream openForPush() throws Http2Exception { switch (state) { case RESERVED_LOCAL: - state = State.HALF_CLOSED_REMOTE; + state = HALF_CLOSED_REMOTE; break; case RESERVED_REMOTE: - state = State.HALF_CLOSED_LOCAL; + state = HALF_CLOSED_LOCAL; break; default: throw protocolError("Attempting to open non-reserved stream for push"); @@ -173,7 +172,7 @@ public class DefaultHttp2Connection implements Http2Connection { public Http2Stream closeLocalSide() { switch (state) { case OPEN: - state = State.HALF_CLOSED_LOCAL; + state = HALF_CLOSED_LOCAL; break; case HALF_CLOSED_LOCAL: break; @@ -188,7 +187,7 @@ public class DefaultHttp2Connection implements Http2Connection { public Http2Stream closeRemoteSide() { switch (state) { case OPEN: - state = State.HALF_CLOSED_REMOTE; + state = HALF_CLOSED_REMOTE; break; case HALF_CLOSED_REMOTE: break; @@ -243,9 +242,9 @@ public class DefaultHttp2Connection implements Http2Connection { // Create and initialize the stream. DefaultStream stream = new DefaultStream(streamId); if (halfClosed) { - stream.state = isLocal() ? State.HALF_CLOSED_LOCAL : State.HALF_CLOSED_REMOTE; + stream.state = isLocal() ? HALF_CLOSED_LOCAL : HALF_CLOSED_REMOTE; } else { - stream.state = State.OPEN; + stream.state = OPEN; } // Update the next and last stream IDs. @@ -278,7 +277,7 @@ public class DefaultHttp2Connection implements Http2Connection { // Create and initialize the stream. DefaultStream stream = new DefaultStream(streamId); - stream.state = isLocal() ? State.RESERVED_LOCAL : State.RESERVED_REMOTE; + stream.state = isLocal() ? RESERVED_LOCAL : RESERVED_REMOTE; // Update the next and last stream IDs. nextStreamId = streamId + 2; diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameReader.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameReader.java index cf67a14ebc..c94dea0c79 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameReader.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameReader.java @@ -575,7 +575,7 @@ public class DefaultHttp2FrameReader implements Http2FrameReader { } } - private void readGoAwayFrame(ChannelHandlerContext ctx, ByteBuf payload, + private static void readGoAwayFrame(ChannelHandlerContext ctx, ByteBuf payload, Http2FrameObserver observer) throws Http2Exception { int lastStreamId = readUnsignedInt(payload); long errorCode = payload.readUnsignedInt(); @@ -620,7 +620,7 @@ public class DefaultHttp2FrameReader implements Http2FrameReader { /** * Base class for processing of HEADERS and PUSH_PROMISE header blocks that potentially span * multiple frames. The implementation of this interface will perform the final callback to the - * {@linkHttp2FrameObserver} once the end of headers is reached. + * {@link Http2FrameObserver} once the end of headers is reached. */ private abstract class HeadersContinuation { private final HeadersBuilder builder = new HeadersBuilder(); @@ -635,7 +635,7 @@ public class DefaultHttp2FrameReader implements Http2FrameReader { * * @param endOfHeaders whether the fragment is the last in the header block. * @param fragment the fragment of the header block to be added. - * @param padding the amount of padding to be supplied to the {@linkHttp2FrameObserver} + * @param padding the amount of padding to be supplied to the {@link Http2FrameObserver} * callback. * @param observer the observer to be notified if the header block is completed. */ diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java index a26eefe44d..de95335096 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java @@ -30,7 +30,6 @@ import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_HEADER_TABLE_ import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_INITIAL_WINDOW_SIZE; import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_MAX_CONCURRENT_STREAMS; import static io.netty.handler.codec.http2.Http2CodecUtil.SETTING_ENTRY_LENGTH; -import static io.netty.handler.codec.http2.Http2CodecUtil.failAndThrow; import static io.netty.handler.codec.http2.Http2CodecUtil.writeUnsignedInt; import static io.netty.handler.codec.http2.Http2CodecUtil.writeUnsignedShort; import static io.netty.util.CharsetUtil.UTF_8; @@ -97,7 +96,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { out.writeZero(padding); return ctx.writeAndFlush(out, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } finally { data.release(); } @@ -105,8 +104,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { @Override public ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, Http2Headers headers, int padding, boolean endStream, boolean endSegment) - throws Http2Exception { + int streamId, Http2Headers headers, int padding, boolean endStream, boolean endSegment) { return writeHeadersInternal(ctx, promise, streamId, headers, padding, endStream, endSegment, false, 0, (short) 0, false); } @@ -114,8 +112,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { @Override public ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, Http2Headers headers, int streamDependency, short weight, - boolean exclusive, int padding, boolean endStream, boolean endSegment) - throws Http2Exception { + boolean exclusive, int padding, boolean endStream, boolean endSegment) { return writeHeadersInternal(ctx, promise, streamId, headers, padding, endStream, endSegment, true, streamDependency, weight, exclusive); } @@ -138,7 +135,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { frame.writeByte(weight - 1); return ctx.writeAndFlush(frame, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } @@ -155,7 +152,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { writeUnsignedInt(errorCode, frame); return ctx.writeAndFlush(frame, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } @@ -197,7 +194,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { } return ctx.writeAndFlush(frame, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } @@ -208,7 +205,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { writeFrameHeader(frame, 0, Http2FrameType.SETTINGS, Http2Flags.ACK_ONLY, 0); return ctx.writeAndFlush(frame, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } @@ -224,7 +221,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { frame.writeBytes(data, data.readerIndex(), data.readableBytes()); return ctx.writeAndFlush(frame, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } finally { data.release(); } @@ -232,8 +229,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { @Override public ChannelFuture writePushPromise(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, int promisedStreamId, Http2Headers headers, int padding) - throws Http2Exception { + int streamId, int promisedStreamId, Http2Headers headers, int padding) { ByteBuf headerBlock = null; try { verifyStreamId(streamId, "Stream ID"); @@ -279,8 +275,8 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { // Create a composite buffer wrapping the first frame and any continuation frames. return continueHeaders(ctx, promise, streamId, padding, headerBlock, firstFrame); - } catch (RuntimeException e) { - throw failAndThrow(promise, e); + } catch (Exception e) { + return promise.setFailure(e); } finally { if (headerBlock != null) { headerBlock.release(); @@ -303,7 +299,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { frame.writeBytes(debugData, debugData.readerIndex(), debugData.readableBytes()); return ctx.writeAndFlush(frame, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } finally { debugData.release(); } @@ -322,7 +318,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { frame.writeInt(windowSizeIncrement); return ctx.writeAndFlush(frame, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } @@ -356,7 +352,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { } return ctx.writeAndFlush(frame, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } finally { protocolId.release(); } @@ -372,7 +368,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { writeFrameHeader(frame, 0, Http2FrameType.BLOCKED, Http2Flags.EMPTY, streamId); return ctx.writeAndFlush(frame, promise); } catch (RuntimeException e) { - throw failAndThrow(promise, e); + return promise.setFailure(e); } } @@ -387,8 +383,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { private ChannelFuture writeHeadersInternal(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, Http2Headers headers, int padding, boolean endStream, boolean endSegment, - boolean hasPriority, int streamDependency, short weight, boolean exclusive) - throws Http2Exception { + boolean hasPriority, int streamDependency, short weight, boolean exclusive) { ByteBuf headerBlock = null; try { verifyStreamId(streamId, "Stream ID"); @@ -445,8 +440,8 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter { // Create a composite buffer wrapping the first frame and any continuation frames. return continueHeaders(ctx, promise, streamId, padding, headerBlock, firstFrame); - } catch (RuntimeException e) { - throw failAndThrow(promise, e); + } catch (Exception e) { + return promise.setFailure(e); } finally { if (headerBlock != null) { headerBlock.release(); diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2OutboundFlowController.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2OutboundFlowController.java index 5dbf3fcc9d..d2de65d3c2 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2OutboundFlowController.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2OutboundFlowController.java @@ -37,6 +37,11 @@ import java.util.concurrent.TimeUnit; * Basic implementation of {@link Http2OutboundFlowController}. */ public class DefaultHttp2OutboundFlowController implements Http2OutboundFlowController { + /** + * The interval (in ns) at which the removed priority garbage collector runs. + */ + private static final long GARBAGE_COLLECTION_INTERVAL = TimeUnit.SECONDS.toNanos(2); + /** * A comparators that sorts priority nodes in ascending order by the amount * of priority data available for its subtree. @@ -577,7 +582,7 @@ public class DefaultHttp2OutboundFlowController implements Http2OutboundFlowCont */ private void incrementPendingBytes(int numBytes) { int previouslyStreamable = streamableBytes(); - this.pendingBytes += numBytes; + pendingBytes += numBytes; incrementPriorityBytes(streamableBytes() - previouslyStreamable); } @@ -688,10 +693,6 @@ public class DefaultHttp2OutboundFlowController implements Http2OutboundFlowCont * Controls garbage collection for priorities that have been marked for removal. */ private final class GarbageCollector implements Runnable { - /** - * The interval (in ns) at which the removed priority garbage collector runs. - */ - private final long GARBAGE_COLLECTION_INTERVAL = TimeUnit.SECONDS.toNanos(2); private final Queue> garbage; private long lastGarbageCollection; diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingHttp2ConnectionHandler.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingHttp2ConnectionHandler.java index 99558ecc7f..4eb5e5acdb 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingHttp2ConnectionHandler.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingHttp2ConnectionHandler.java @@ -59,32 +59,28 @@ public class DelegatingHttp2ConnectionHandler extends AbstractHttp2ConnectionHan @Override public ChannelFuture writeData(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, - ByteBuf data, int padding, boolean endStream, boolean endSegment, boolean compressed) - throws Http2Exception { + ByteBuf data, int padding, boolean endStream, boolean endSegment, boolean compressed) { return super.writeData(ctx, promise, streamId, data, padding, endStream, endSegment, compressed); } @Override public ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, Http2Headers headers, int padding, boolean endStream, boolean endSegment) - throws Http2Exception { + int streamId, Http2Headers headers, int padding, boolean endStream, boolean endSegment) { return super.writeHeaders(ctx, promise, streamId, headers, padding, endStream, endSegment); } @Override public ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, Http2Headers headers, int streamDependency, short weight, - boolean exclusive, int padding, boolean endStream, boolean endSegment) - throws Http2Exception { + boolean exclusive, int padding, boolean endStream, boolean endSegment) { return super.writeHeaders(ctx, promise, streamId, headers, streamDependency, weight, exclusive, padding, endStream, endSegment); } @Override public ChannelFuture writePriority(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, int streamDependency, short weight, boolean exclusive) - throws Http2Exception { + int streamId, int streamDependency, short weight, boolean exclusive) { return super.writePriority(ctx, promise, streamId, streamDependency, weight, exclusive); } @@ -96,27 +92,24 @@ public class DelegatingHttp2ConnectionHandler extends AbstractHttp2ConnectionHan @Override public ChannelFuture writeSettings(ChannelHandlerContext ctx, ChannelPromise promise, - Http2Settings settings) throws Http2Exception { + Http2Settings settings) { return super.writeSettings(ctx, promise, settings); } @Override - public ChannelFuture writePing(ChannelHandlerContext ctx, ChannelPromise promise, ByteBuf data) - throws Http2Exception { + public ChannelFuture writePing(ChannelHandlerContext ctx, ChannelPromise promise, ByteBuf data) { return super.writePing(ctx, promise, data); } @Override public ChannelFuture writePushPromise(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, int promisedStreamId, Http2Headers headers, int padding) - throws Http2Exception { + int streamId, int promisedStreamId, Http2Headers headers, int padding) { return super.writePushPromise(ctx, promise, streamId, promisedStreamId, headers, padding); } @Override public ChannelFuture writeAltSvc(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, long maxAge, int port, ByteBuf protocolId, String host, String origin) - throws Http2Exception { + int streamId, long maxAge, int port, ByteBuf protocolId, String host, String origin) { return super.writeAltSvc(ctx, promise, streamId, maxAge, port, protocolId, host, origin); } diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameObserver.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameObserver.java index db545889af..adc7dfdf80 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameObserver.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameObserver.java @@ -133,7 +133,7 @@ public interface Http2FrameObserver { * @param streamId the stream the frame was sent on. * @param promisedStreamId the ID of the promised stream. * @param headers the received headers. - * @param paddingthe number of padding bytes found at the end of the frame. + * @param padding the number of padding bytes found at the end of the frame. */ void onPushPromiseRead(ChannelHandlerContext ctx, int streamId, int promisedStreamId, Http2Headers headers, int padding) throws Http2Exception; diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameType.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameType.java index f1944b2fc0..28e5525e4d 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameType.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameType.java @@ -49,7 +49,7 @@ public enum Http2FrameType { private final short code; - private Http2FrameType(short code) { + Http2FrameType(short code) { this.code = code; } diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameWriter.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameWriter.java index d70068c0a3..bf5d51596b 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameWriter.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2FrameWriter.java @@ -41,8 +41,7 @@ public interface Http2FrameWriter extends Closeable { * @return the future for the write. */ ChannelFuture writeData(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, - ByteBuf data, int padding, boolean endStream, boolean endSegment, boolean compressed) - throws Http2Exception; + ByteBuf data, int padding, boolean endStream, boolean endSegment, boolean compressed); /** * Writes a HEADERS frame to the remote endpoint. @@ -57,8 +56,7 @@ public interface Http2FrameWriter extends Closeable { * @return the future for the write. */ ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, - Http2Headers headers, int padding, boolean endStream, boolean endSegment) - throws Http2Exception; + Http2Headers headers, int padding, boolean endStream, boolean endSegment); /** * Writes a HEADERS frame with priority specified to the remote endpoint. @@ -78,7 +76,7 @@ public interface Http2FrameWriter extends Closeable { */ ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, - int padding, boolean endStream, boolean endSegment) throws Http2Exception; + int padding, boolean endStream, boolean endSegment); /** * Writes a PRIORITY frame to the remote endpoint. @@ -93,7 +91,7 @@ public interface Http2FrameWriter extends Closeable { * @return the future for the write. */ ChannelFuture writePriority(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, - int streamDependency, short weight, boolean exclusive) throws Http2Exception; + int streamDependency, short weight, boolean exclusive); /** * Writes a RST_STREAM frame to the remote endpoint. @@ -116,7 +114,7 @@ public interface Http2FrameWriter extends Closeable { * @return the future for the write. */ ChannelFuture writeSettings(ChannelHandlerContext ctx, ChannelPromise promise, - Http2Settings settings) throws Http2Exception; + Http2Settings settings); /** * Writes a SETTINGS acknowledgment to the remote endpoint. @@ -125,8 +123,7 @@ public interface Http2FrameWriter extends Closeable { * @param promise the promise for the write. * @return the future for the write. */ - ChannelFuture writeSettingsAck(ChannelHandlerContext ctx, ChannelPromise promise) - throws Http2Exception; + ChannelFuture writeSettingsAck(ChannelHandlerContext ctx, ChannelPromise promise); /** * Writes a PING frame to the remote endpoint. @@ -139,7 +136,7 @@ public interface Http2FrameWriter extends Closeable { * @return the future for the write. */ ChannelFuture writePing(ChannelHandlerContext ctx, ChannelPromise promise, boolean ack, - ByteBuf data) throws Http2Exception; + ByteBuf data); /** * Writes a PUSH_PROMISE frame to the remote endpoint. @@ -153,7 +150,7 @@ public interface Http2FrameWriter extends Closeable { * @return the future for the write. */ ChannelFuture writePushPromise(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, - int promisedStreamId, Http2Headers headers, int padding) throws Http2Exception; + int promisedStreamId, Http2Headers headers, int padding); /** * Writes a GO_AWAY frame to the remote endpoint. @@ -179,7 +176,7 @@ public interface Http2FrameWriter extends Closeable { * @return the future for the write. */ ChannelFuture writeWindowUpdate(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, int windowSizeIncrement) throws Http2Exception; + int streamId, int windowSizeIncrement); /** * Writes a ALT_SVC frame to the remote endpoint. @@ -196,8 +193,7 @@ public interface Http2FrameWriter extends Closeable { * @return the future for the write. */ ChannelFuture writeAltSvc(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, - long maxAge, int port, ByteBuf protocolId, String host, String origin) - throws Http2Exception; + long maxAge, int port, ByteBuf protocolId, String host, String origin); /** * Writes a BLOCKED frame to the remote endpoint. @@ -207,8 +203,7 @@ public interface Http2FrameWriter extends Closeable { * @param streamId the stream that is blocked or 0 if the entire connection is blocked. * @return the future for the write. */ - ChannelFuture writeBlocked(ChannelHandlerContext ctx, ChannelPromise promise, int streamId) - throws Http2Exception; + ChannelFuture writeBlocked(ChannelHandlerContext ctx, ChannelPromise promise, int streamId); /** * Closes this writer and frees any allocated resources. diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2OutboundFlowController.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2OutboundFlowController.java index 82927f27f4..a7799e2080 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2OutboundFlowController.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2OutboundFlowController.java @@ -23,7 +23,7 @@ import io.netty.buffer.ByteBuf; public interface Http2OutboundFlowController { /** - * Interface that abstracts the writing of {@link Http2Frame} objects to the remote endpoint. + * Interface that abstracts the writing of frames to the remote endpoint. */ interface FrameWriter { diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2OutboundFrameLogger.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2OutboundFrameLogger.java index 6207eb440a..60c26693c0 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2OutboundFrameLogger.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2OutboundFrameLogger.java @@ -43,8 +43,7 @@ public class Http2OutboundFrameLogger implements Http2FrameWriter { @Override public ChannelFuture writeData(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, - ByteBuf data, int padding, boolean endStream, boolean endSegment, boolean compressed) - throws Http2Exception { + ByteBuf data, int padding, boolean endStream, boolean endSegment, boolean compressed) { logger.logData(OUTBOUND, streamId, data, padding, endStream, endSegment, compressed); return writer.writeData(ctx, promise, streamId, data, padding, endStream, endSegment, compressed); @@ -52,8 +51,7 @@ public class Http2OutboundFrameLogger implements Http2FrameWriter { @Override public ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, Http2Headers headers, int padding, boolean endStream, boolean endSegment) - throws Http2Exception { + int streamId, Http2Headers headers, int padding, boolean endStream, boolean endSegment) { logger.logHeaders(OUTBOUND, streamId, headers, padding, endStream, endSegment); return writer.writeHeaders(ctx, promise, streamId, headers, padding, endStream, endSegment); } @@ -61,8 +59,7 @@ public class Http2OutboundFrameLogger implements Http2FrameWriter { @Override public ChannelFuture writeHeaders(ChannelHandlerContext ctx, ChannelPromise promise, int streamId, Http2Headers headers, int streamDependency, short weight, - boolean exclusive, int padding, boolean endStream, boolean endSegment) - throws Http2Exception { + boolean exclusive, int padding, boolean endStream, boolean endSegment) { logger.logHeaders(OUTBOUND, streamId, headers, streamDependency, weight, exclusive, padding, endStream, endSegment); return writer.writeHeaders(ctx, promise, streamId, headers, streamDependency, weight, @@ -71,8 +68,7 @@ public class Http2OutboundFrameLogger implements Http2FrameWriter { @Override public ChannelFuture writePriority(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, int streamDependency, short weight, boolean exclusive) - throws Http2Exception { + int streamId, int streamDependency, short weight, boolean exclusive) { logger.logPriority(OUTBOUND, streamId, streamDependency, weight, exclusive); return writer.writePriority(ctx, promise, streamId, streamDependency, weight, exclusive); } @@ -85,29 +81,27 @@ public class Http2OutboundFrameLogger implements Http2FrameWriter { @Override public ChannelFuture writeSettings(ChannelHandlerContext ctx, ChannelPromise promise, - Http2Settings settings) throws Http2Exception { + Http2Settings settings) { logger.logSettings(OUTBOUND, settings); return writer.writeSettings(ctx, promise, settings); } @Override - public ChannelFuture writeSettingsAck(ChannelHandlerContext ctx, ChannelPromise promise) - throws Http2Exception { + public ChannelFuture writeSettingsAck(ChannelHandlerContext ctx, ChannelPromise promise) { logger.logSettingsAck(OUTBOUND); return writer.writeSettingsAck(ctx, promise); } @Override public ChannelFuture writePing(ChannelHandlerContext ctx, ChannelPromise promise, boolean ack, - ByteBuf data) throws Http2Exception { + ByteBuf data) { logger.logPing(OUTBOUND, data); return writer.writePing(ctx, promise, ack, data); } @Override public ChannelFuture writePushPromise(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, int promisedStreamId, Http2Headers headers, int padding) - throws Http2Exception { + int streamId, int promisedStreamId, Http2Headers headers, int padding) { logger.logPushPromise(OUTBOUND, streamId, promisedStreamId, headers, padding); return writer.writePushPromise(ctx, promise, streamId, promisedStreamId, headers, padding); } @@ -121,22 +115,21 @@ public class Http2OutboundFrameLogger implements Http2FrameWriter { @Override public ChannelFuture writeWindowUpdate(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, int windowSizeIncrement) throws Http2Exception { + int streamId, int windowSizeIncrement) { logger.logWindowsUpdate(OUTBOUND, streamId, windowSizeIncrement); return writer.writeWindowUpdate(ctx, promise, streamId, windowSizeIncrement); } @Override public ChannelFuture writeAltSvc(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId, long maxAge, int port, ByteBuf protocolId, String host, String origin) - throws Http2Exception { + int streamId, long maxAge, int port, ByteBuf protocolId, String host, String origin) { logger.logAltSvc(OUTBOUND, streamId, maxAge, port, protocolId, host, origin); return writer.writeAltSvc(ctx, promise, streamId, maxAge, port, protocolId, host, origin); } @Override public ChannelFuture writeBlocked(ChannelHandlerContext ctx, ChannelPromise promise, - int streamId) throws Http2Exception { + int streamId) { logger.logBlocked(OUTBOUND, streamId); return writer.writeBlocked(ctx, promise, streamId); } diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2PriorityTree.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2PriorityTree.java index 79b34c8f81..40b3c9ae6e 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2PriorityTree.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2PriorityTree.java @@ -101,7 +101,6 @@ public interface Http2PriorityTree extends Iterable prioritizeUsingDefaults(int streamId); diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Settings.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Settings.java index 5a1bbcb59d..7b6788c248 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Settings.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Settings.java @@ -62,7 +62,7 @@ public class Http2Settings { } enable(MAX_HEADER_TABLE_SIZE_MASK); - this.maxHeaderTableSize = headerTableSize; + maxHeaderTableSize = headerTableSize; return this; } diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DelegatingHttp2ConnectionHandlerTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DelegatingHttp2ConnectionHandlerTest.java index 56ef154c8d..317709a948 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DelegatingHttp2ConnectionHandlerTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DelegatingHttp2ConnectionHandlerTest.java @@ -50,6 +50,7 @@ import io.netty.channel.ChannelPromise; import java.util.Arrays; import java.util.Collections; +import io.netty.channel.DefaultChannelPromise; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -88,7 +89,6 @@ public class DelegatingHttp2ConnectionHandlerTest { @Mock private Channel channel; - @Mock private ChannelPromise promise; @Mock @@ -112,6 +112,9 @@ public class DelegatingHttp2ConnectionHandlerTest { @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); + + promise = new DefaultChannelPromise(channel); + when(channel.isActive()).thenReturn(true); when(stream.id()).thenReturn(STREAM_ID); when(stream.state()).thenReturn(OPEN); @@ -492,16 +495,18 @@ public class DelegatingHttp2ConnectionHandlerTest { eq(host), eq(origin)); } - @Test(expected = Http2Exception.class) + @Test public void dataWriteAfterGoAwayShouldFail() throws Exception { when(connection.isGoAway()).thenReturn(true); - handler.writeData(ctx, promise, STREAM_ID, dummyData(), 0, false, false, false); + ChannelFuture future = handler.writeData(ctx, promise, STREAM_ID, dummyData(), 0, false, false, false); + assertTrue(future.awaitUninterruptibly().cause() instanceof Http2Exception); } - @Test(expected = Http2Exception.class) + @Test public void dataWriteShouldDisallowCompression() throws Exception { when(local.allowCompressedData()).thenReturn(false); - handler.writeData(ctx, promise, STREAM_ID, dummyData(), 0, false, false, true); + ChannelFuture future = handler.writeData(ctx, promise, STREAM_ID, dummyData(), 0, false, false, true); + assertTrue(future.awaitUninterruptibly().cause() instanceof Http2Exception); } @Test @@ -519,14 +524,16 @@ public class DelegatingHttp2ConnectionHandlerTest { eq(false), eq(false), any(Http2OutboundFlowController.FrameWriter.class)); } - @Test(expected = Http2Exception.class) + @Test public void headersWriteAfterGoAwayShouldFail() throws Exception { when(connection.isGoAway()).thenReturn(true); - handler.writeHeaders(ctx, promise, 5, EMPTY_HEADERS, 0, (short) 255, false, 0, false, false); + ChannelFuture future = handler.writeHeaders( + ctx, promise, 5, EMPTY_HEADERS, 0, (short) 255, false, 0, false, false); verify(writer, never()).writeHeaders(eq(ctx), eq(promise), anyInt(), any(Http2Headers.class), anyInt(), anyBoolean(), anyBoolean()); verify(outboundFlow, never()).addStream(anyInt(), anyInt(), anyShort(), anyBoolean()); verify(inboundFlow, never()).addStream(anyInt()); + assertTrue(future.awaitUninterruptibly().cause() instanceof Http2Exception); } @Test @@ -569,10 +576,11 @@ public class DelegatingHttp2ConnectionHandlerTest { eq(DEFAULT_PRIORITY_WEIGHT), eq(false), eq(0), eq(true), eq(false)); } - @Test(expected = Http2Exception.class) + @Test public void pushPromiseWriteAfterGoAwayShouldFail() throws Exception { when(connection.isGoAway()).thenReturn(true); - handler.writePushPromise(ctx, promise, STREAM_ID, PUSH_STREAM_ID, EMPTY_HEADERS, 0); + ChannelFuture future = handler.writePushPromise(ctx, promise, STREAM_ID, PUSH_STREAM_ID, EMPTY_HEADERS, 0); + assertTrue(future.awaitUninterruptibly().cause() instanceof Http2Exception); } @Test @@ -583,10 +591,11 @@ public class DelegatingHttp2ConnectionHandlerTest { eq(EMPTY_HEADERS), eq(0)); } - @Test(expected = Http2Exception.class) + @Test public void priorityWriteAfterGoAwayShouldFail() throws Exception { when(connection.isGoAway()).thenReturn(true); - handler.writePriority(ctx, promise, STREAM_ID, 0, (short) 255, true); + ChannelFuture future = handler.writePriority(ctx, promise, STREAM_ID, 0, (short) 255, true); + assertTrue(future.awaitUninterruptibly().cause() instanceof Http2Exception); } @Test @@ -611,10 +620,11 @@ public class DelegatingHttp2ConnectionHandlerTest { eq((long) PROTOCOL_ERROR.code())); } - @Test(expected = Http2Exception.class) + @Test public void pingWriteAfterGoAwayShouldFail() throws Exception { when(connection.isGoAway()).thenReturn(true); - handler.writePing(ctx, promise, emptyPingBuf()); + ChannelFuture future = handler.writePing(ctx, promise, emptyPingBuf()); + assertTrue(future.awaitUninterruptibly().cause() instanceof Http2Exception); } @Test @@ -623,10 +633,11 @@ public class DelegatingHttp2ConnectionHandlerTest { verify(writer).writePing(eq(ctx), eq(promise), eq(false), eq(emptyPingBuf())); } - @Test(expected = Http2Exception.class) + @Test public void settingsWriteAfterGoAwayShouldFail() throws Exception { when(connection.isGoAway()).thenReturn(true); - handler.writeSettings(ctx, promise, new Http2Settings()); + ChannelFuture future = handler.writeSettings(ctx, promise, new Http2Settings()); + assertTrue(future.awaitUninterruptibly().cause() instanceof Http2Exception); } @Test @@ -654,11 +665,12 @@ public class DelegatingHttp2ConnectionHandlerTest { verify(reader).maxHeaderTableSize(eq(2000)); } - @Test(expected = Http2Exception.class) + @Test public void clientWriteAltSvcShouldThrow() throws Exception { when(connection.isServer()).thenReturn(false); - handler.writeAltSvc(ctx, promise, STREAM_ID, 1, 2, Unpooled.EMPTY_BUFFER, + ChannelFuture future = handler.writeAltSvc(ctx, promise, STREAM_ID, 1, 2, Unpooled.EMPTY_BUFFER, "www.example.com", null); + assertTrue(future.awaitUninterruptibly().cause() instanceof Http2Exception); } @Test diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java index 377d7b5d5b..c4cdb60736 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java @@ -120,14 +120,10 @@ public class Http2ConnectionRoundtripTest { clientChannel.eventLoop().execute(new Runnable() { @Override public void run() { - try { - http2Client.writeHeaders(ctx(), newPromise(), streamId, headers, 0, - (short) 16, false, 0, false, false); - http2Client.writeData(ctx(), newPromise(), streamId, - Unpooled.copiedBuffer(text.getBytes()), 0, true, true, false); - } catch (Http2Exception e) { - throw new RuntimeException(e); - } + http2Client.writeHeaders(ctx(), newPromise(), streamId, headers, 0, + (short) 16, false, 0, false, false); + http2Client.writeData(ctx(), newPromise(), streamId, + Unpooled.copiedBuffer(text.getBytes()), 0, true, true, false); } }); }