From 9f5b2c51b7f096f933e5b0448631cf5044110544 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Fri, 12 Feb 2016 15:30:09 -0800 Subject: [PATCH] ByteToMessageDecoder ChannelInputShutdownEvent support Motivation: b714297a44ced34643fa60ca854f1880d02ba649 introduced ChannelInputShutdownEvent support for HttpObjectDecoder. However this should have been added to the super class ByteToMessageDecoder, and ByteToMessageDecoder should not propegate a channelInactive event through the pipeline in this case. Modifications: - Move the ChannelInputShutdownEvent handling from HttpObjectDecoder to ByteToMessageDecoder - ByteToMessageDecoder doesn't call ctx.fireChannelInactive() on ChannelInputShutdownEvent Result: Half closed events are treated more generically, and don't get translated into a channelInactive pipeline event. --- .../handler/codec/http/HttpObjectDecoder.java | 8 +------- .../handler/codec/ByteToMessageDecoder.java | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java index d2a662bbd7..c0d443ae27 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java @@ -20,7 +20,6 @@ import io.netty.buffer.ByteBufProcessor; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.ChannelInputShutdownEvent; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.DecoderResult; import io.netty.handler.codec.TooLongFrameException; @@ -433,12 +432,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder { @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - if (evt instanceof ChannelInputShutdownEvent) { - // The decodeLast method is invoked when a channelInactive event is encountered. - // This method is responsible for ending requests in some situations and must be called - // when the input has been shutdown. - super.channelInactive(ctx); - } else if (evt instanceof HttpExpectationFailedEvent) { + if (evt instanceof HttpExpectationFailedEvent) { switch (currentState) { case READ_FIXED_LENGTH_CONTENT: case READ_VARIABLE_LENGTH_CONTENT: diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java index cb18d38379..98620292b2 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java @@ -21,6 +21,7 @@ import io.netty.buffer.CompositeByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.socket.ChannelInputShutdownEvent; import io.netty.util.internal.RecyclableArrayList; import io.netty.util.internal.StringUtil; @@ -305,6 +306,21 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { + channelInputClosed(ctx, true); + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof ChannelInputShutdownEvent) { + // The decodeLast method is invoked when a channelInactive event is encountered. + // This method is responsible for ending requests in some situations and must be called + // when the input has been shutdown. + channelInputClosed(ctx, false); + } + super.userEventTriggered(ctx, evt); + } + + private void channelInputClosed(ChannelHandlerContext ctx, boolean callChannelInactive) throws Exception { RecyclableArrayList out = RecyclableArrayList.newInstance(); try { if (cumulation != null) { @@ -329,7 +345,9 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter // Something was read, call fireChannelReadComplete() ctx.fireChannelReadComplete(); } - ctx.fireChannelInactive(); + if (callChannelInactive) { + ctx.fireChannelInactive(); + } } finally { // recycle in all cases out.recycle();