Class 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, XmlDecoder, XmlFrameDecoder, ZlibDecoder
ChannelInboundHandlerAdapter which decodes bytes in a stream-like fashion from one ByteBuf to
another Message type.
For example here is an implementation which reads all readable bytes from
the input ByteBuf and create a new ByteBuf.
public class SquareDecoder extends ByteToMessageDecoder {
@Override
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
throws Exception {
out.add(in.readBytes(in.readableBytes()));
}
}
Frame detection
Generally frame detection should be handled earlier in the pipeline by adding a
DelimiterBasedFrameDecoder, FixedLengthFrameDecoder, LengthFieldBasedFrameDecoder,
or LineBasedFrameDecoder.
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 checking ByteBuf.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 like ByteBuf.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 subclasses of ByteToMessageDecoder MUST NOT
annotated with
invalid @link
{@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 out List. Use derived buffers like ByteBuf.readSlice(int)
to avoid leaking memory.
-
Nested Class Summary
Nested ClassesNested classes/interfaces inherited from interface ChannelHandler
ChannelHandler.Sharable -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final ByteToMessageDecoder.CumulatorCumulateByteBufs by add them to aCompositeByteBufand so do no memory copy whenever possible.(package private) ByteBufprivate ByteToMessageDecoder.Cumulatorprivate byteA bitmask where the bits are defined asSTATE_INITSTATE_CALLING_CHILD_DECODESTATE_HANDLER_REMOVED_PENDINGprivate intprivate booleanThis flag is used to determine if we need to callChannelHandlerContext.read()to consume more data whenChannelConfig.isAutoRead()isfalse.private booleanstatic final ByteToMessageDecoder.Cumulatorprivate intprivate booleanprivate booleanprivate static final byteprivate static final byteprivate static final byte -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected intReturns the actual number of readable bytes in the internal cumulative buffer of this decoder.protected voidcallDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) Called once data should be decoded from the givenByteBuf.voidCallsChannelHandlerContext.fireChannelInactive()to forward to the nextChannelInboundHandlerin theChannelPipeline.private voidchannelInputClosed(ChannelHandlerContext ctx, boolean callChannelInactive) (package private) voidchannelInputClosed(ChannelHandlerContext ctx, List<Object> out) Called when the input of the channel was closed which may be because it changed to inactive or because ofChannelInputShutdownEvent.voidchannelRead(ChannelHandlerContext ctx, Object input) CallsChannelHandlerContext.fireChannelRead(Object)to forward to the nextChannelInboundHandlerin theChannelPipeline.voidCallsChannelHandlerContext.fireChannelReadComplete()to forward to the nextChannelInboundHandlerin theChannelPipeline.protected abstract voiddecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) Decode the from oneByteBufto an other.protected voiddecodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) Is called one last time when theChannelHandlerContextgoes in-active.(package private) final voiddecodeRemovalReentryProtection(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) Decode the from oneByteBufto an other.protected final void(package private) static ByteBufexpandCumulation(ByteBufAllocator alloc, ByteBuf oldCumulation, ByteBuf in) (package private) static voidfireChannelRead(ChannelHandlerContext ctx, CodecOutputList msgs, int numElements) GetnumElementsout of theCodecOutputListand forward these through the pipeline.(package private) static voidfireChannelRead(ChannelHandlerContext ctx, List<Object> msgs, int numElements) GetnumElementsout of theListand forward these through the pipeline.final voidDo nothing by default, sub-classes may override this method.protected voidGets called after theByteToMessageDecoderwas removed from the actual context and it doesn't handle events anymore.protected ByteBufReturns the internal cumulative buffer of this decoder.booleanIftruethen only one message is decoded on eachchannelRead(ChannelHandlerContext, Object)call.voidsetCumulator(ByteToMessageDecoder.Cumulator cumulator) Set theByteToMessageDecoder.Cumulatorto use for cumulate the receivedByteBufs.voidsetDiscardAfterReads(int discardAfterReads) Set the number of reads after whichByteBuf.discardSomeReadBytes()are called and so free up memory.voidsetSingleDecode(boolean singleDecode) If set then only one message is decoded on eachchannelRead(ChannelHandlerContext, Object)call.voiduserEventTriggered(ChannelHandlerContext ctx, Object evt) CallsChannelHandlerContext.fireUserEventTriggered(Object)to forward to the nextChannelInboundHandlerin theChannelPipeline.Methods inherited from class ChannelInboundHandlerAdapter
channelActive, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaughtMethods inherited from class ChannelHandlerAdapter
ensureNotSharable, handlerAdded, isSharableMethods inherited from class Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface ChannelHandler
handlerAdded
-
Field Details
-
MERGE_CUMULATOR
-
COMPOSITE_CUMULATOR
CumulateByteBufs by add them to aCompositeByteBufand so do no memory copy whenever possible. Be aware thatCompositeByteBufuse a more complex indexing implementation so depending on your use-case and the decoder implementation this may be slower than just use theMERGE_CUMULATOR. -
STATE_INIT
private static final byte STATE_INIT- See Also:
-
STATE_CALLING_CHILD_DECODE
private static final byte STATE_CALLING_CHILD_DECODE- See Also:
-
STATE_HANDLER_REMOVED_PENDING
private static final byte STATE_HANDLER_REMOVED_PENDING- See Also:
-
inputMessages
-
cumulation
ByteBuf cumulation -
cumulator
-
singleDecode
private boolean singleDecode -
first
private boolean first -
firedChannelRead
private boolean firedChannelReadThis flag is used to determine if we need to callChannelHandlerContext.read()to consume more data whenChannelConfig.isAutoRead()isfalse. -
selfFiredChannelRead
private boolean selfFiredChannelRead -
decodeState
private byte decodeStateA bitmask where the bits are defined as -
discardAfterReads
private int discardAfterReads -
numReads
private int numReads
-
-
Constructor Details
-
ByteToMessageDecoder
protected ByteToMessageDecoder()
-
-
Method Details
-
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 isfalseas this has performance impacts. -
isSingleDecode
public boolean isSingleDecode()Iftruethen only one message is decoded on eachchannelRead(ChannelHandlerContext, Object)call. Default isfalseas this has performance impacts. -
setCumulator
Set theByteToMessageDecoder.Cumulatorto use for cumulate the receivedByteBufs. -
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
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
Description copied from class:ChannelHandlerAdapterDo nothing by default, sub-classes may override this method.- Specified by:
handlerRemovedin interfaceChannelHandler- Overrides:
handlerRemovedin classChannelHandlerAdapter- Throws:
Exception
-
handlerRemoved0
Gets called after theByteToMessageDecoderwas removed from the actual context and it doesn't handle events anymore.- Throws:
Exception
-
channelRead
Description copied from class:ChannelInboundHandlerAdapterCallsChannelHandlerContext.fireChannelRead(Object)to forward to the nextChannelInboundHandlerin theChannelPipeline. Sub-classes may override this method to change behavior.- Specified by:
channelReadin interfaceChannelInboundHandler- Overrides:
channelReadin classChannelInboundHandlerAdapter- Throws:
Exception
-
fireChannelRead
GetnumElementsout of theListand forward these through the pipeline. -
fireChannelRead
GetnumElementsout of theCodecOutputListand forward these through the pipeline. -
channelReadComplete
Description copied from class:ChannelInboundHandlerAdapterCallsChannelHandlerContext.fireChannelReadComplete()to forward to the nextChannelInboundHandlerin theChannelPipeline. Sub-classes may override this method to change behavior.- Specified by:
channelReadCompletein interfaceChannelInboundHandler- Overrides:
channelReadCompletein classChannelInboundHandlerAdapter- Throws:
Exception
-
discardSomeReadBytes
protected final void discardSomeReadBytes() -
channelInactive
Description copied from class:ChannelInboundHandlerAdapterCallsChannelHandlerContext.fireChannelInactive()to forward to the nextChannelInboundHandlerin theChannelPipeline. Sub-classes may override this method to change behavior.- Specified by:
channelInactivein interfaceChannelInboundHandler- Overrides:
channelInactivein classChannelInboundHandlerAdapter- Throws:
Exception
-
userEventTriggered
Description copied from class:ChannelInboundHandlerAdapterCallsChannelHandlerContext.fireUserEventTriggered(Object)to forward to the nextChannelInboundHandlerin theChannelPipeline. Sub-classes may override this method to change behavior.- Specified by:
userEventTriggeredin interfaceChannelInboundHandler- Overrides:
userEventTriggeredin classChannelInboundHandlerAdapter- Throws:
Exception
-
channelInputClosed
-
channelInputClosed
Called when the input of the channel was closed which may be because it changed to inactive or because ofChannelInputShutdownEvent.- Throws:
Exception
-
callDecode
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- theChannelHandlerContextwhich thisByteToMessageDecoderbelongs toin- theByteBuffrom which to read dataout- theListto which decoded messages should be added
-
decode
protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception Decode the from oneByteBufto an other. This method will be called till either the inputByteBufhas nothing to read when return from this method or till nothing was read from the inputByteBuf.- Parameters:
ctx- theChannelHandlerContextwhich thisByteToMessageDecoderbelongs toin- theByteBuffrom which to read dataout- theListto which decoded messages should be added- Throws:
Exception- is thrown if an error occurs
-
decodeRemovalReentryProtection
final void decodeRemovalReentryProtection(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception Decode the from oneByteBufto an other. This method will be called till either the inputByteBufhas nothing to read when return from this method or till nothing was read from the inputByteBuf.- Parameters:
ctx- theChannelHandlerContextwhich thisByteToMessageDecoderbelongs toin- theByteBuffrom which to read dataout- theListto which decoded messages should be added- Throws:
Exception- is thrown if an error occurs
-
decodeLast
Is called one last time when theChannelHandlerContextgoes 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:
Exception
-
expandCumulation
-