From 97f2fa734133bde9aff1a572aef2f0620542cfa6 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Mon, 18 Mar 2013 13:58:48 +0900 Subject: [PATCH] Allow a user specify the byte order of the length field for LengthFieldBasedFrameDecoder - Fixes #1164 --- .../codec/LengthFieldBasedFrameDecoder.java | 90 ++++++++++++++----- 1 file changed, 68 insertions(+), 22 deletions(-) diff --git a/codec/src/main/java/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java index 3160fb54f3..a42f923b8e 100644 --- a/codec/src/main/java/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java @@ -20,6 +20,8 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.serialization.ObjectDecoder; +import java.nio.ByteOrder; + /** * A decoder that splits the received {@link ByteBuf}s dynamically by the * value of the length field in the message. It is particularly useful when you @@ -181,6 +183,7 @@ import io.netty.handler.codec.serialization.ObjectDecoder; */ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder { + private final ByteOrder byteOrder; private final int maxFrameLength; private final int lengthFieldOffset; private final int lengthFieldLength; @@ -260,9 +263,45 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder { * has been read. */ public LengthFieldBasedFrameDecoder( - int maxFrameLength, - int lengthFieldOffset, int lengthFieldLength, + int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) { + this( + ByteOrder.BIG_ENDIAN, maxFrameLength, lengthFieldOffset, lengthFieldLength, + lengthAdjustment, initialBytesToStrip, failFast); + } + + /** + * Creates a new instance. + * + * @param byteOrder + * the {@link ByteOrder} of the length field + * @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 true, a {@link TooLongFrameException} is thrown as + * soon as the decoder notices the length of the frame will exceed + * maxFrameLength regardless of whether the entire frame + * has been read. If false, a {@link TooLongFrameException} + * is thrown after the entire frame that exceeds maxFrameLength + * has been read. + */ + public LengthFieldBasedFrameDecoder( + ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, + int lengthAdjustment, int initialBytesToStrip, boolean failFast) { + if (byteOrder == null) { + throw new NullPointerException("byteOrder"); + } + if (maxFrameLength <= 0) { throw new IllegalArgumentException( "maxFrameLength must be a positive integer: " + @@ -297,6 +336,7 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder { "lengthFieldLength (" + lengthFieldLength + ")."); } + this.byteOrder = byteOrder; this.maxFrameLength = maxFrameLength; this.lengthFieldOffset = lengthFieldOffset; this.lengthFieldLength = lengthFieldLength; @@ -323,26 +363,7 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder { } int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset; - long frameLength; - switch (lengthFieldLength) { - case 1: - frameLength = in.getUnsignedByte(actualLengthFieldOffset); - break; - case 2: - frameLength = in.getUnsignedShort(actualLengthFieldOffset); - break; - case 3: - frameLength = in.getUnsignedMedium(actualLengthFieldOffset); - break; - case 4: - frameLength = in.getUnsignedInt(actualLengthFieldOffset); - break; - case 8: - frameLength = in.getLong(actualLengthFieldOffset); - break; - default: - throw new Error("should not reach here"); - } + long frameLength = getFrameLength(in, actualLengthFieldOffset); if (frameLength < 0) { in.skipBytes(lengthFieldEndOffset); @@ -391,6 +412,31 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder { return frame; } + private long getFrameLength(ByteBuf in, int actualLengthFieldOffset) { + in = in.order(byteOrder); + long frameLength; + switch (lengthFieldLength) { + case 1: + frameLength = in.getUnsignedByte(actualLengthFieldOffset); + break; + case 2: + frameLength = in.getUnsignedShort(actualLengthFieldOffset); + break; + case 3: + frameLength = in.getUnsignedMedium(actualLengthFieldOffset); + break; + case 4: + frameLength = in.getUnsignedInt(actualLengthFieldOffset); + break; + case 8: + frameLength = in.getLong(actualLengthFieldOffset); + break; + default: + throw new Error("should not reach here"); + } + return frameLength; + } + private void failIfNecessary(ChannelHandlerContext ctx, boolean firstDetectionOfTooLongFrame) { if (bytesToDiscard == 0) { // Reset to the initial state and tell the handlers that