diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToByteDecoder.java b/codec/src/main/java/io/netty/handler/codec/ByteToByteDecoder.java index 334bcb12e5..31a3cf7e3e 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToByteDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToByteDecoder.java @@ -44,6 +44,28 @@ import io.netty.channel.ChannelInboundByteHandlerAdapter; */ public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter { + private volatile boolean singleDecode; + + /** + * If set then only one message is decoded on each {@link #inboundBufferUpdated(ChannelHandlerContext)} call. + * This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up. + * + * Default is {@code false} as this has performance impacts. + */ + public void setSingleDecode(boolean singleDecode) { + this.singleDecode = singleDecode; + } + + /** + * If {@code true} then only one message is decoded on each + * {@link #inboundBufferUpdated(ChannelHandlerContext)} call. + * + * Default is {@code false} as this has performance impacts. + */ + public boolean isSingleDecode() { + return singleDecode; + } + @Override public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) throws Exception { callDecode(ctx, in, ctx.nextInboundByteBuffer()); @@ -91,7 +113,7 @@ public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter ctx.fireExceptionCaught(new DecoderException(t)); } } - if (oldInSize == in.readableBytes()) { + if (oldInSize == in.readableBytes() || isSingleDecode()) { break; } } 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 b32b095f57..d82e8c6b23 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java @@ -44,6 +44,28 @@ public abstract class ByteToMessageDecoder private ChannelHandlerContext ctx; + private volatile boolean singleDecode; + + /** + * If set then only one message is decoded on each {@link #inboundBufferUpdated(ChannelHandlerContext)} call. + * This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up. + * + * Default is {@code false} as this has performance impacts. + */ + public void setSingleDecode(boolean singleDecode) { + this.singleDecode = singleDecode; + } + + /** + * If {@code true} then only one message is decoded on each + * {@link #inboundBufferUpdated(ChannelHandlerContext)} call. + * + * Default is {@code false} as this has performance impacts. + */ + public boolean isSingleDecode() { + return singleDecode; + } + @Override public void beforeAdd(ChannelHandlerContext ctx) throws Exception { this.ctx = ctx; @@ -109,6 +131,9 @@ public abstract class ByteToMessageDecoder if (ChannelHandlerUtil.unfoldAndAdd(ctx, o, true)) { decoded = true; + if (isSingleDecode()) { + break; + } } else { break; } diff --git a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoder.java b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoder.java index 02743758d4..76bc1a0400 100644 --- a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoder.java @@ -432,6 +432,9 @@ public abstract class ReplayingDecoder extends ByteToMessageDecoder { // A successful decode if (ChannelHandlerUtil.unfoldAndAdd(ctx, result, true)) { decoded = true; + if (isSingleDecode()) { + break; + } } } catch (Throwable t) { if (decoded) {