diff --git a/codec/src/main/java/io/netty/handler/codec/LineBasedFrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/LineBasedFrameDecoder.java index 7ab4bff183..305981b762 100644 --- a/codec/src/main/java/io/netty/handler/codec/LineBasedFrameDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/LineBasedFrameDecoder.java @@ -39,6 +39,9 @@ public class LineBasedFrameDecoder extends ByteToMessageDecoder { private boolean discarding; private int discardedBytes; + /** Last scan position. */ + private int offset; + /** * Creates a new decoder. * @param maxLength the maximum length of the decoded frame. @@ -114,6 +117,7 @@ public class LineBasedFrameDecoder extends ByteToMessageDecoder { discardedBytes = length; buffer.readerIndex(buffer.writerIndex()); discarding = true; + offset = 0; if (failFast) { fail(ctx, "over " + discardedBytes); } @@ -152,10 +156,16 @@ public class LineBasedFrameDecoder extends ByteToMessageDecoder { * Returns the index in the buffer of the end of line found. * Returns -1 if no end of line was found in the buffer. */ - private static int findEndOfLine(final ByteBuf buffer) { - int i = buffer.forEachByte(ByteProcessor.FIND_LF); - if (i > 0 && buffer.getByte(i - 1) == '\r') { - i--; + private int findEndOfLine(final ByteBuf buffer) { + int totalLength = buffer.readableBytes(); + int i = buffer.forEachByte(buffer.readerIndex() + offset, totalLength - offset, ByteProcessor.FIND_LF); + if (i >= 0) { + offset = 0; + if (i > 0 && buffer.getByte(i - 1) == '\r') { + i--; + } + } else { + offset = totalLength; } return i; } diff --git a/codec/src/test/java/io/netty/handler/codec/LineBasedFrameDecoderTest.java b/codec/src/test/java/io/netty/handler/codec/LineBasedFrameDecoderTest.java index b462874e61..b68c38bbbe 100644 --- a/codec/src/test/java/io/netty/handler/codec/LineBasedFrameDecoderTest.java +++ b/codec/src/test/java/io/netty/handler/codec/LineBasedFrameDecoderTest.java @@ -167,4 +167,22 @@ public class LineBasedFrameDecoderTest { buf.release(); buf2.release(); } + + @Test + public void testEmptyLine() throws Exception { + EmbeddedChannel ch = new EmbeddedChannel(new LineBasedFrameDecoder(8192, true, false)); + + assertTrue(ch.writeInbound(copiedBuffer("\nabcna\r\n", CharsetUtil.US_ASCII))); + + ByteBuf buf = ch.readInbound(); + assertEquals("", buf.toString(CharsetUtil.US_ASCII)); + + ByteBuf buf2 = ch.readInbound(); + assertEquals("abcna", buf2.toString(CharsetUtil.US_ASCII)); + + assertFalse(ch.finishAndReleaseAll()); + + buf.release(); + buf2.release(); + } }