Allow a user specify the byte order of the length field for LengthFieldBasedFrameDecoder
- Fixes #1164
This commit is contained in:
parent
660e6f4afe
commit
97f2fa7341
@ -20,6 +20,8 @@ import io.netty.buffer.Unpooled;
|
|||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||||
|
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A decoder that splits the received {@link ByteBuf}s dynamically by the
|
* 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
|
* 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 {
|
public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder {
|
||||||
|
|
||||||
|
private final ByteOrder byteOrder;
|
||||||
private final int maxFrameLength;
|
private final int maxFrameLength;
|
||||||
private final int lengthFieldOffset;
|
private final int lengthFieldOffset;
|
||||||
private final int lengthFieldLength;
|
private final int lengthFieldLength;
|
||||||
@ -260,9 +263,45 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder {
|
|||||||
* has been read.
|
* has been read.
|
||||||
*/
|
*/
|
||||||
public LengthFieldBasedFrameDecoder(
|
public LengthFieldBasedFrameDecoder(
|
||||||
int maxFrameLength,
|
int maxFrameLength, int lengthFieldOffset, int lengthFieldLength,
|
||||||
int lengthFieldOffset, int lengthFieldLength,
|
|
||||||
int lengthAdjustment, int initialBytesToStrip, boolean failFast) {
|
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 <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(
|
||||||
|
ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength,
|
||||||
|
int lengthAdjustment, int initialBytesToStrip, boolean failFast) {
|
||||||
|
if (byteOrder == null) {
|
||||||
|
throw new NullPointerException("byteOrder");
|
||||||
|
}
|
||||||
|
|
||||||
if (maxFrameLength <= 0) {
|
if (maxFrameLength <= 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"maxFrameLength must be a positive integer: " +
|
"maxFrameLength must be a positive integer: " +
|
||||||
@ -297,6 +336,7 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder {
|
|||||||
"lengthFieldLength (" + lengthFieldLength + ").");
|
"lengthFieldLength (" + lengthFieldLength + ").");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.byteOrder = byteOrder;
|
||||||
this.maxFrameLength = maxFrameLength;
|
this.maxFrameLength = maxFrameLength;
|
||||||
this.lengthFieldOffset = lengthFieldOffset;
|
this.lengthFieldOffset = lengthFieldOffset;
|
||||||
this.lengthFieldLength = lengthFieldLength;
|
this.lengthFieldLength = lengthFieldLength;
|
||||||
@ -323,26 +363,7 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset;
|
int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset;
|
||||||
long frameLength;
|
long frameLength = getFrameLength(in, actualLengthFieldOffset);
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frameLength < 0) {
|
if (frameLength < 0) {
|
||||||
in.skipBytes(lengthFieldEndOffset);
|
in.skipBytes(lengthFieldEndOffset);
|
||||||
@ -391,6 +412,31 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder {
|
|||||||
return frame;
|
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) {
|
private void failIfNecessary(ChannelHandlerContext ctx, boolean firstDetectionOfTooLongFrame) {
|
||||||
if (bytesToDiscard == 0) {
|
if (bytesToDiscard == 0) {
|
||||||
// Reset to the initial state and tell the handlers that
|
// Reset to the initial state and tell the handlers that
|
||||||
|
Loading…
x
Reference in New Issue
Block a user