Consistent fail-fast property

* DelimiterBasedFrameDecoder and LengthFieldBasedFrameDecoder must
expose the fail-fast option consistently
* Renamed failImmediatelyOnTooLongFrame to failFast
This commit is contained in:
Trustin Lee 2011-11-22 18:39:11 +09:00
parent 0d4dfefeb0
commit 0da39901c8
4 changed files with 91 additions and 42 deletions

View File

@ -67,9 +67,9 @@ public class DelimiterBasedFrameDecoder extends FrameDecoder {
private final ChannelBuffer[] delimiters;
private final int maxFrameLength;
private final boolean stripDelimiter;
private final boolean failFast;
private boolean discardingTooLongFrame;
private int tooLongFrameLength;
private final boolean failImmediatelyOnTooLongFrame;
/**
* Creates a new instance.
@ -95,6 +95,29 @@ public class DelimiterBasedFrameDecoder extends FrameDecoder {
*/
public DelimiterBasedFrameDecoder(
int maxFrameLength, boolean stripDelimiter, ChannelBuffer delimiter) {
this(maxFrameLength, stripDelimiter, false, delimiter);
}
/**
* Creates a new instance.
*
* @param maxFrameLength the maximum length of the decoded frame.
* A {@link TooLongFrameException} is thrown if
* the length of the frame exceeds this value.
* @param stripDelimiter whether the decoded frame should strip out the
* delimiter or not
* @param failFast If <tt>true</tt>, a {@link TooLongFrameException} is
* thrown as soon as the decoder notices the length of the
* frame will exceed <tt>maxFrameLength</tt> regardless of
* whether the entire frame has been read.
* If <tt>false</tt>, a {@link TooLongFrameException} is
* thrown after the entire frame that exceeds
* <tt>maxFrameLength</tt> has been read.
* @param delimiter the delimiter
*/
public DelimiterBasedFrameDecoder(
int maxFrameLength, boolean stripDelimiter, boolean failFast,
ChannelBuffer delimiter) {
validateMaxFrameLength(maxFrameLength);
validateDelimiter(delimiter);
delimiters = new ChannelBuffer[] {
@ -103,7 +126,7 @@ public class DelimiterBasedFrameDecoder extends FrameDecoder {
};
this.maxFrameLength = maxFrameLength;
this.stripDelimiter = stripDelimiter;
this.failImmediatelyOnTooLongFrame = false;
this.failFast = failFast;
}
/**
@ -119,7 +142,14 @@ public class DelimiterBasedFrameDecoder extends FrameDecoder {
}
/**
* Calls {@link #DelimiterBasedFrameDecoder(int, boolean, boolean, ChannelBuffer...)} with failImmediatelyOnTooLongFrame set to <code>false</code>
* Creates a new instance.
*
* @param maxFrameLength the maximum length of the decoded frame.
* A {@link TooLongFrameException} is thrown if
* the length of the frame exceeds this value.
* @param stripDelimiter whether the decoded frame should strip out the
* delimiter or not
* @param delimiters the delimiters
*/
public DelimiterBasedFrameDecoder(
int maxFrameLength, boolean stripDelimiter, ChannelBuffer... delimiters) {
@ -134,16 +164,17 @@ public class DelimiterBasedFrameDecoder extends FrameDecoder {
* the length of the frame exceeds this value.
* @param stripDelimiter whether the decoded frame should strip out the
* delimiter or not
* @param failImmediatelyOnTooLongFrame If false (the default) a {@link TooLongFrameException}
* is thrown if the length of the frame exceeds maxFrameLength,
* after the delimiter has been read.
* If true a {@link TooLongFrameException} is thrown immediately
* when the length of the frame exceeds maxFrameLength,
* regardless of whether a delimiter has been found yet.
* @param failFast If <tt>true</tt>, a {@link TooLongFrameException} is
* thrown as soon as the decoder notices the length of the
* frame will exceed <tt>maxFrameLength</tt> regardless of
* whether the entire frame has been read.
* If <tt>false</tt>, a {@link TooLongFrameException} is
* thrown after the entire frame that exceeds
* <tt>maxFrameLength</tt> has been read.
* @param delimiters the delimiters
*/
public DelimiterBasedFrameDecoder(
int maxFrameLength, boolean stripDelimiter, boolean failImmediatelyOnTooLongFrame, ChannelBuffer... delimiters) {
int maxFrameLength, boolean stripDelimiter, boolean failFast, ChannelBuffer... delimiters) {
validateMaxFrameLength(maxFrameLength);
if (delimiters == null) {
throw new NullPointerException("delimiters");
@ -159,7 +190,7 @@ public class DelimiterBasedFrameDecoder extends FrameDecoder {
}
this.maxFrameLength = maxFrameLength;
this.stripDelimiter = stripDelimiter;
this.failImmediatelyOnTooLongFrame = failImmediatelyOnTooLongFrame;
this.failFast = failFast;
}
@Override
@ -188,7 +219,7 @@ public class DelimiterBasedFrameDecoder extends FrameDecoder {
int tooLongFrameLength = this.tooLongFrameLength;
this.tooLongFrameLength = 0;
if (!failImmediatelyOnTooLongFrame) {
if (!failFast) {
fail(ctx, tooLongFrameLength);
}
return null;
@ -216,7 +247,7 @@ public class DelimiterBasedFrameDecoder extends FrameDecoder {
tooLongFrameLength = buffer.readableBytes();
buffer.skipBytes(buffer.readableBytes());
discardingTooLongFrame = true;
if (failImmediatelyOnTooLongFrame) {
if (failFast) {
fail(ctx, tooLongFrameLength);
}
}

View File

@ -198,7 +198,7 @@ public class LengthFieldBasedFrameDecoder extends FrameDecoder {
private boolean discardingTooLongFrame;
private long tooLongFrameLength;
private long bytesToDiscard;
private boolean failImmediatelyOnTooLongFrame = false;
private boolean failFast;
/**
* Creates a new instance.
@ -239,6 +239,39 @@ public class LengthFieldBasedFrameDecoder extends FrameDecoder {
int maxFrameLength,
int lengthFieldOffset, int lengthFieldLength,
int lengthAdjustment, int initialBytesToStrip) {
this(
maxFrameLength,
lengthFieldOffset, lengthFieldLength, lengthAdjustment,
initialBytesToStrip, false);
}
/**
* Creates a new instance.
*
* @param maxFrameLength
* the maximum length of the frame. If the length of the frame is
* greater than this value, {@link TooLongFrameException} will be
* thrown.
* @param lengthFieldOffset
* the offset of the length field
* @param lengthFieldLength
* the length of the length field
* @param lengthAdjustment
* the compensation value to add to the value of the length field
* @param initialBytesToStrip
* the number of first bytes to strip out from the decoded frame
* @param failFast
* If <tt>true</tt>, a {@link TooLongFrameException} is thrown as
* soon as the decoder notices the length of the frame will exceed
* <tt>maxFrameLength</tt> regardless of whether the entire frame
* has been read. If <tt>false</tt>, a {@link TooLongFrameException}
* is thrown after the entire frame that exceeds <tt>maxFrameLength</tt>
* has been read.
*/
public LengthFieldBasedFrameDecoder(
int maxFrameLength,
int lengthFieldOffset, int lengthFieldLength,
int lengthAdjustment, int initialBytesToStrip, boolean failFast) {
if (maxFrameLength <= 0) {
throw new IllegalArgumentException(
"maxFrameLength must be a positive integer: " +
@ -279,6 +312,7 @@ public class LengthFieldBasedFrameDecoder extends FrameDecoder {
this.lengthAdjustment = lengthAdjustment;
lengthFieldEndOffset = lengthFieldOffset + lengthFieldLength;
this.initialBytesToStrip = initialBytesToStrip;
this.failFast = failFast;
}
@Override
@ -374,14 +408,14 @@ public class LengthFieldBasedFrameDecoder extends FrameDecoder {
long tooLongFrameLength = this.tooLongFrameLength;
this.tooLongFrameLength = 0;
discardingTooLongFrame = false;
if ((!failImmediatelyOnTooLongFrame) ||
(failImmediatelyOnTooLongFrame && firstDetectionOfTooLongFrame))
if ((!failFast) ||
(failFast && firstDetectionOfTooLongFrame))
{
fail(ctx, tooLongFrameLength);
}
} else {
// Keep discarding and notify handlers if necessary.
if (failImmediatelyOnTooLongFrame && firstDetectionOfTooLongFrame)
if (failFast && firstDetectionOfTooLongFrame)
{
fail(ctx, this.tooLongFrameLength);
}
@ -410,23 +444,6 @@ public class LengthFieldBasedFrameDecoder extends FrameDecoder {
return frame;
}
/**
* Set the behavior when a frame longer than maxFrameLength is encountered.
*
* @param failImmediatelyOnTooLongFrame If false (the default) a {@link TooLongFrameException}
* is thrown if the length of the frame exceeds maxFrameLength,
* after the entire frame has been read.
* If true a {@link TooLongFrameException} is thrown immediately
* when the length of the frame exceeds maxFrameLength,
* regardless of whether the entire frame has been read.
*/
public LengthFieldBasedFrameDecoder setFailImmediatelyOnTooLongFrame(
boolean failImmediatelyOnTooLongFrame)
{
this.failImmediatelyOnTooLongFrame = failImmediatelyOnTooLongFrame;
return this;
}
private void fail(ChannelHandlerContext ctx, long frameLength) {
if (frameLength > 0) {
Channels.fireExceptionCaught(

View File

@ -28,13 +28,14 @@ import org.junit.Test;
*/
public class DelimiterBasedFrameDecoderTest {
@Test
public void testTooLongFrameRecovery() throws Exception {
public void testFailSlowTooLongFrameRecovery() throws Exception {
DecoderEmbedder<ChannelBuffer> embedder = new DecoderEmbedder<ChannelBuffer>(
new DelimiterBasedFrameDecoder(1, Delimiters.nulDelimiter()));
for (int i = 0; i < 2; i ++) {
embedder.offer(ChannelBuffers.wrappedBuffer(new byte[] { 1, 2 }));
try {
embedder.offer(ChannelBuffers.wrappedBuffer(new byte[] { 1, 2, 0 }));
embedder.offer(ChannelBuffers.wrappedBuffer(new byte[] { 0 }));
Assert.fail(CodecEmbedderException.class.getSimpleName() + " must be raised.");
} catch (CodecEmbedderException e) {
Assert.assertTrue(e.getCause() instanceof TooLongFrameException);
@ -48,7 +49,7 @@ public class DelimiterBasedFrameDecoderTest {
}
@Test
public void testFailImmediatelyTooLongFrameRecovery() throws Exception {
public void testFailFastTooLongFrameRecovery() throws Exception {
DecoderEmbedder<ChannelBuffer> embedder = new DecoderEmbedder<ChannelBuffer>(
new DelimiterBasedFrameDecoder(1, true, true, Delimiters.nulDelimiter()));

View File

@ -28,13 +28,14 @@ import org.junit.Test;
*/
public class LengthFieldBasedFrameDecoderTest {
@Test
public void testTooLongFrameRecovery() throws Exception {
public void testFailSlowTooLongFrameRecovery() throws Exception {
DecoderEmbedder<ChannelBuffer> embedder = new DecoderEmbedder<ChannelBuffer>(
new LengthFieldBasedFrameDecoder(5, 0, 4, 0, 4));
for (int i = 0; i < 2; i ++) {
embedder.offer(ChannelBuffers.wrappedBuffer(new byte[] { 0, 0, 0, 2 }));
try {
embedder.offer(ChannelBuffers.wrappedBuffer(new byte[] { 0, 0, 0, 2, 0, 0 }));
embedder.offer(ChannelBuffers.wrappedBuffer(new byte[] { 0, 0 }));
Assert.fail(CodecEmbedderException.class.getSimpleName() + " must be raised.");
} catch (CodecEmbedderException e) {
Assert.assertTrue(e.getCause() instanceof TooLongFrameException);
@ -48,10 +49,9 @@ public class LengthFieldBasedFrameDecoderTest {
}
@Test
public void testFailImmediatelyTooLongFrameRecovery() throws Exception {
public void testFailFastTooLongFrameRecovery() throws Exception {
DecoderEmbedder<ChannelBuffer> embedder = new DecoderEmbedder<ChannelBuffer>(
new LengthFieldBasedFrameDecoder(5, 0, 4, 0, 4).
setFailImmediatelyOnTooLongFrame(true));
new LengthFieldBasedFrameDecoder(5, 0, 4, 0, 4, true));
for (int i = 0; i < 2; i ++) {
try {