Class ByteToMessageDecoder
- java.lang.Object
-
- io.netty.channel.ChannelHandlerAdapter
-
- io.netty.channel.ChannelInboundHandlerAdapter
-
- io.netty.handler.codec.ByteToMessageDecoder
-
- All Implemented Interfaces:
ChannelHandler
,ChannelInboundHandler
- Direct Known Subclasses:
AbstractMemcacheObjectDecoder
,Bzip2Decoder
,CleartextHttp2ServerUpgradeHandler
,DelimiterBasedFrameDecoder
,FastLzFrameDecoder
,FixedLengthFrameDecoder
,HAProxyMessageDecoder
,Http2ConnectionHandler
,HttpObjectDecoder
,JsonObjectDecoder
,LengthFieldBasedFrameDecoder
,LineBasedFrameDecoder
,OptionalSslHandler
,RedisDecoder
,ReplayingDecoder
,SnappyFrameDecoder
,SocksPortUnificationServerHandler
,SpdyFrameCodec
,SslClientHelloHandler
,SslHandler
,WebSocket08FrameDecoder
,XmlFrameDecoder
,ZlibDecoder
public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
ChannelInboundHandlerAdapter
which decodes bytes in a stream-like fashion from oneByteBuf
to an other Message type. For example here is an implementation which reads all readable bytes from the inputByteBuf
and create a newByteBuf
.public class SquareDecoder extends
ByteToMessageDecoder
{@Override
public void decode(ChannelHandlerContext
ctx,ByteBuf
in, List<Object> out) throwsException
{ out.add(in.readBytes(in.readableBytes())); } }Frame detection
Generally frame detection should be handled earlier in the pipeline by adding a
DelimiterBasedFrameDecoder
,FixedLengthFrameDecoder
,LengthFieldBasedFrameDecoder
, orLineBasedFrameDecoder
.If a custom frame decoder is required, then one needs to be careful when implementing one with
ByteToMessageDecoder
. Ensure there are enough bytes in the buffer for a complete frame by checkingByteBuf.readableBytes()
. If there are not enough bytes for a complete frame, return without modifying the reader index to allow more bytes to arrive.To check for complete frames without modifying the reader index, use methods like
ByteBuf.getInt(int)
. One MUST use the reader index when using methods likeByteBuf.getInt(int)
. For example calling in.getInt(0) is assuming the frame starts at the beginning of the buffer, which is not always the case. Use in.getInt(in.readerIndex()) instead.Pitfalls
Be aware that sub-classes of
ByteToMessageDecoder
MUST NOT annotated with {@link @Sharable}.Some methods such as
ByteBuf.readBytes(int)
will cause a memory leak if the returned buffer is not released or added to the outList
. Use derived buffers likeByteBuf.readSlice(int)
to avoid leaking memory.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interface
ByteToMessageDecoder.Cumulator
CumulateByteBuf
s.-
Nested classes/interfaces inherited from interface io.netty.channel.ChannelHandler
ChannelHandler.Sharable
-
-
Field Summary
Fields Modifier and Type Field Description static ByteToMessageDecoder.Cumulator
COMPOSITE_CUMULATOR
CumulateByteBuf
s by add them to aCompositeByteBuf
and so do no memory copy whenever possible.(package private) ByteBuf
cumulation
private ByteToMessageDecoder.Cumulator
cumulator
private byte
decodeState
A bitmask where the bits are defined asSTATE_INIT
STATE_CALLING_CHILD_DECODE
STATE_HANDLER_REMOVED_PENDING
private int
discardAfterReads
private boolean
firedChannelRead
This flag is used to determine if we need to callChannelHandlerContext.read()
to consume more data whenChannelConfig.isAutoRead()
isfalse
.private boolean
first
static ByteToMessageDecoder.Cumulator
MERGE_CUMULATOR
private int
numReads
private boolean
singleDecode
private static byte
STATE_CALLING_CHILD_DECODE
private static byte
STATE_HANDLER_REMOVED_PENDING
private static byte
STATE_INIT
-
Constructor Summary
Constructors Modifier Constructor Description protected
ByteToMessageDecoder()
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description protected int
actualReadableBytes()
Returns the actual number of readable bytes in the internal cumulative buffer of this decoder.protected void
callDecode(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out)
Called once data should be decoded from the givenByteBuf
.void
channelInactive(ChannelHandlerContext ctx)
CallsChannelHandlerContext.fireChannelInactive()
to forward to the nextChannelInboundHandler
in theChannelPipeline
.private void
channelInputClosed(ChannelHandlerContext ctx, boolean callChannelInactive)
(package private) void
channelInputClosed(ChannelHandlerContext ctx, java.util.List<java.lang.Object> out)
Called when the input of the channel was closed which may be because it changed to inactive or because ofChannelInputShutdownEvent
.void
channelRead(ChannelHandlerContext ctx, java.lang.Object msg)
CallsChannelHandlerContext.fireChannelRead(Object)
to forward to the nextChannelInboundHandler
in theChannelPipeline
.void
channelReadComplete(ChannelHandlerContext ctx)
CallsChannelHandlerContext.fireChannelReadComplete()
to forward to the nextChannelInboundHandler
in theChannelPipeline
.protected abstract void
decode(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out)
Decode the from oneByteBuf
to an other.protected void
decodeLast(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out)
Is called one last time when theChannelHandlerContext
goes in-active.(package private) void
decodeRemovalReentryProtection(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out)
Decode the from oneByteBuf
to an other.protected void
discardSomeReadBytes()
(package private) static ByteBuf
expandCumulation(ByteBufAllocator alloc, ByteBuf oldCumulation, ByteBuf in)
(package private) static void
fireChannelRead(ChannelHandlerContext ctx, CodecOutputList msgs, int numElements)
GetnumElements
out of theCodecOutputList
and forward these through the pipeline.(package private) static void
fireChannelRead(ChannelHandlerContext ctx, java.util.List<java.lang.Object> msgs, int numElements)
GetnumElements
out of theList
and forward these through the pipeline.void
handlerRemoved(ChannelHandlerContext ctx)
Do nothing by default, sub-classes may override this method.protected void
handlerRemoved0(ChannelHandlerContext ctx)
Gets called after theByteToMessageDecoder
was removed from the actual context and it doesn't handle events anymore.protected ByteBuf
internalBuffer()
Returns the internal cumulative buffer of this decoder.boolean
isSingleDecode()
Iftrue
then only one message is decoded on eachchannelRead(ChannelHandlerContext, Object)
call.void
setCumulator(ByteToMessageDecoder.Cumulator cumulator)
Set theByteToMessageDecoder.Cumulator
to use for cumulate the receivedByteBuf
s.void
setDiscardAfterReads(int discardAfterReads)
Set the number of reads after whichByteBuf.discardSomeReadBytes()
are called and so free up memory.void
setSingleDecode(boolean singleDecode)
If set then only one message is decoded on eachchannelRead(ChannelHandlerContext, Object)
call.void
userEventTriggered(ChannelHandlerContext ctx, java.lang.Object evt)
CallsChannelHandlerContext.fireUserEventTriggered(Object)
to forward to the nextChannelInboundHandler
in theChannelPipeline
.-
Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter
channelActive, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaught
-
Methods inherited from class io.netty.channel.ChannelHandlerAdapter
ensureNotSharable, handlerAdded, isSharable
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface io.netty.channel.ChannelHandler
handlerAdded
-
-
-
-
Field Detail
-
MERGE_CUMULATOR
public static final ByteToMessageDecoder.Cumulator MERGE_CUMULATOR
-
COMPOSITE_CUMULATOR
public static final ByteToMessageDecoder.Cumulator COMPOSITE_CUMULATOR
CumulateByteBuf
s by add them to aCompositeByteBuf
and so do no memory copy whenever possible. Be aware thatCompositeByteBuf
use a more complex indexing implementation so depending on your use-case and the decoder implementation this may be slower then just use theMERGE_CUMULATOR
.
-
STATE_INIT
private static final byte STATE_INIT
- See Also:
- Constant Field Values
-
STATE_CALLING_CHILD_DECODE
private static final byte STATE_CALLING_CHILD_DECODE
- See Also:
- Constant Field Values
-
STATE_HANDLER_REMOVED_PENDING
private static final byte STATE_HANDLER_REMOVED_PENDING
- See Also:
- Constant Field Values
-
cumulation
ByteBuf cumulation
-
cumulator
private ByteToMessageDecoder.Cumulator cumulator
-
singleDecode
private boolean singleDecode
-
first
private boolean first
-
firedChannelRead
private boolean firedChannelRead
This flag is used to determine if we need to callChannelHandlerContext.read()
to consume more data whenChannelConfig.isAutoRead()
isfalse
.
-
decodeState
private byte decodeState
A bitmask where the bits are defined as
-
discardAfterReads
private int discardAfterReads
-
numReads
private int numReads
-
-
Method Detail
-
setSingleDecode
public void setSingleDecode(boolean singleDecode)
If set then only one message is decoded on eachchannelRead(ChannelHandlerContext, Object)
call. This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up. Default isfalse
as this has performance impacts.
-
isSingleDecode
public boolean isSingleDecode()
Iftrue
then only one message is decoded on eachchannelRead(ChannelHandlerContext, Object)
call. Default isfalse
as this has performance impacts.
-
setCumulator
public void setCumulator(ByteToMessageDecoder.Cumulator cumulator)
Set theByteToMessageDecoder.Cumulator
to use for cumulate the receivedByteBuf
s.
-
setDiscardAfterReads
public void setDiscardAfterReads(int discardAfterReads)
Set the number of reads after whichByteBuf.discardSomeReadBytes()
are called and so free up memory. The default is16
.
-
actualReadableBytes
protected int actualReadableBytes()
Returns the actual number of readable bytes in the internal cumulative buffer of this decoder. You usually do not need to rely on this value to write a decoder. Use it only when you must use it at your own risk. This method is a shortcut tointernalBuffer().readableBytes()
.
-
internalBuffer
protected ByteBuf internalBuffer()
Returns the internal cumulative buffer of this decoder. You usually do not need to access the internal buffer directly to write a decoder. Use it only when you must use it at your own risk.
-
handlerRemoved
public final void handlerRemoved(ChannelHandlerContext ctx) throws java.lang.Exception
Description copied from class:ChannelHandlerAdapter
Do nothing by default, sub-classes may override this method.- Specified by:
handlerRemoved
in interfaceChannelHandler
- Overrides:
handlerRemoved
in classChannelHandlerAdapter
- Throws:
java.lang.Exception
-
handlerRemoved0
protected void handlerRemoved0(ChannelHandlerContext ctx) throws java.lang.Exception
Gets called after theByteToMessageDecoder
was removed from the actual context and it doesn't handle events anymore.- Throws:
java.lang.Exception
-
channelRead
public void channelRead(ChannelHandlerContext ctx, java.lang.Object msg) throws java.lang.Exception
Description copied from class:ChannelInboundHandlerAdapter
CallsChannelHandlerContext.fireChannelRead(Object)
to forward to the nextChannelInboundHandler
in theChannelPipeline
. Sub-classes may override this method to change behavior.- Specified by:
channelRead
in interfaceChannelInboundHandler
- Overrides:
channelRead
in classChannelInboundHandlerAdapter
- Throws:
java.lang.Exception
-
fireChannelRead
static void fireChannelRead(ChannelHandlerContext ctx, java.util.List<java.lang.Object> msgs, int numElements)
GetnumElements
out of theList
and forward these through the pipeline.
-
fireChannelRead
static void fireChannelRead(ChannelHandlerContext ctx, CodecOutputList msgs, int numElements)
GetnumElements
out of theCodecOutputList
and forward these through the pipeline.
-
channelReadComplete
public void channelReadComplete(ChannelHandlerContext ctx) throws java.lang.Exception
Description copied from class:ChannelInboundHandlerAdapter
CallsChannelHandlerContext.fireChannelReadComplete()
to forward to the nextChannelInboundHandler
in theChannelPipeline
. Sub-classes may override this method to change behavior.- Specified by:
channelReadComplete
in interfaceChannelInboundHandler
- Overrides:
channelReadComplete
in classChannelInboundHandlerAdapter
- Throws:
java.lang.Exception
-
discardSomeReadBytes
protected final void discardSomeReadBytes()
-
channelInactive
public void channelInactive(ChannelHandlerContext ctx) throws java.lang.Exception
Description copied from class:ChannelInboundHandlerAdapter
CallsChannelHandlerContext.fireChannelInactive()
to forward to the nextChannelInboundHandler
in theChannelPipeline
. Sub-classes may override this method to change behavior.- Specified by:
channelInactive
in interfaceChannelInboundHandler
- Overrides:
channelInactive
in classChannelInboundHandlerAdapter
- Throws:
java.lang.Exception
-
userEventTriggered
public void userEventTriggered(ChannelHandlerContext ctx, java.lang.Object evt) throws java.lang.Exception
Description copied from class:ChannelInboundHandlerAdapter
CallsChannelHandlerContext.fireUserEventTriggered(Object)
to forward to the nextChannelInboundHandler
in theChannelPipeline
. Sub-classes may override this method to change behavior.- Specified by:
userEventTriggered
in interfaceChannelInboundHandler
- Overrides:
userEventTriggered
in classChannelInboundHandlerAdapter
- Throws:
java.lang.Exception
-
channelInputClosed
private void channelInputClosed(ChannelHandlerContext ctx, boolean callChannelInactive)
-
channelInputClosed
void channelInputClosed(ChannelHandlerContext ctx, java.util.List<java.lang.Object> out) throws java.lang.Exception
Called when the input of the channel was closed which may be because it changed to inactive or because ofChannelInputShutdownEvent
.- Throws:
java.lang.Exception
-
callDecode
protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out)
Called once data should be decoded from the givenByteBuf
. This method will calldecode(ChannelHandlerContext, ByteBuf, List)
as long as decoding should take place.- Parameters:
ctx
- theChannelHandlerContext
which thisByteToMessageDecoder
belongs toin
- theByteBuf
from which to read dataout
- theList
to which decoded messages should be added
-
decode
protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out) throws java.lang.Exception
Decode the from oneByteBuf
to an other. This method will be called till either the inputByteBuf
has nothing to read when return from this method or till nothing was read from the inputByteBuf
.- Parameters:
ctx
- theChannelHandlerContext
which thisByteToMessageDecoder
belongs toin
- theByteBuf
from which to read dataout
- theList
to which decoded messages should be added- Throws:
java.lang.Exception
- is thrown if an error occurs
-
decodeRemovalReentryProtection
final void decodeRemovalReentryProtection(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out) throws java.lang.Exception
Decode the from oneByteBuf
to an other. This method will be called till either the inputByteBuf
has nothing to read when return from this method or till nothing was read from the inputByteBuf
.- Parameters:
ctx
- theChannelHandlerContext
which thisByteToMessageDecoder
belongs toin
- theByteBuf
from which to read dataout
- theList
to which decoded messages should be added- Throws:
java.lang.Exception
- is thrown if an error occurs
-
decodeLast
protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out) throws java.lang.Exception
Is called one last time when theChannelHandlerContext
goes in-active. Which means thechannelInactive(ChannelHandlerContext)
was triggered. By default this will just calldecode(ChannelHandlerContext, ByteBuf, List)
but sub-classes may override this for some special cleanup operation.- Throws:
java.lang.Exception
-
expandCumulation
static ByteBuf expandCumulation(ByteBufAllocator alloc, ByteBuf oldCumulation, ByteBuf in)
-
-