Class ByteToMessageDecoder
- java.lang.Object
-
- io.netty.channel.ChannelHandlerAdapter
-
- io.netty.channel.ChannelInboundHandlerAdapter
-
- io.servicetalk.transport.netty.internal.ByteToMessageDecoder
-
- All Implemented Interfaces:
io.netty.channel.ChannelHandler
,io.netty.channel.ChannelInboundHandler
public abstract class ByteToMessageDecoder extends io.netty.channel.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 callingin.getInt(0)
is assuming the frame starts at the beginning of the buffer, which is not always the case. Usein.getInt(in.readerIndex())
instead.Pitfalls
Be aware that sub-classes of
ByteToMessageDecoder
MUST NOT annotated withChannelHandler.Sharable
.Some methods such as
ByteBuf.readBytes(int)
will cause a memory leak if the returned buffer is not released or added to theout
List
. Use derived buffers likeByteBuf.readSlice(int)
to avoid leaking memory.
-
-
Constructor Summary
Constructors Modifier Constructor Description protected
ByteToMessageDecoder(io.netty.buffer.ByteBufAllocator cumulationAllocator)
Create a new instance.
-
Method Summary
All Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description void
channelInactive(io.netty.channel.ChannelHandlerContext ctx)
void
channelRead(io.netty.channel.ChannelHandlerContext ctx, java.lang.Object msg)
void
channelReadComplete(io.netty.channel.ChannelHandlerContext ctx)
protected void
cumulationReset()
Resets cumulation.protected abstract void
decode(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in)
Decode the from oneByteBuf
to an other.protected void
decodeLast(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in)
Is called one last time when theChannelHandlerContext
goes in-active.void
handlerRemoved(io.netty.channel.ChannelHandlerContext ctx)
protected void
handlerRemoved0(io.netty.channel.ChannelHandlerContext ctx)
Gets called after theByteToMessageDecoder
was removed from the actual context and it doesn't handle events anymore.protected io.netty.buffer.ByteBuf
swapAndCopyCumulation(io.netty.buffer.ByteBuf cumulation, io.netty.buffer.ByteBuf in)
Swap the existingcumulation
ByteBuf
for a newByteBuf
and copyin
.void
userEventTriggered(io.netty.channel.ChannelHandlerContext ctx, java.lang.Object evt)
-
Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter
channelActive, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaught
-
Methods inherited from class io.netty.channel.ChannelHandlerAdapter
ensureNotSharable, handlerAdded, isSharable
-
-
-
-
Constructor Detail
-
ByteToMessageDecoder
protected ByteToMessageDecoder(io.netty.buffer.ByteBufAllocator cumulationAllocator)
Create a new instance.- Parameters:
cumulationAllocator
- UnpooledByteBufAllocator
used to allocate more memory, if necessary for cumulation.- Throws:
java.lang.IllegalArgumentException
- if the providedcumulationAllocator
is not unpooled.
-
-
Method Detail
-
handlerRemoved
public final void handlerRemoved(io.netty.channel.ChannelHandlerContext ctx)
- Specified by:
handlerRemoved
in interfaceio.netty.channel.ChannelHandler
- Overrides:
handlerRemoved
in classio.netty.channel.ChannelHandlerAdapter
-
handlerRemoved0
protected void handlerRemoved0(io.netty.channel.ChannelHandlerContext ctx)
Gets called after theByteToMessageDecoder
was removed from the actual context and it doesn't handle events anymore.- Parameters:
ctx
- theChannelHandlerContext
which thisByteToMessageDecoder
belongs to
-
channelRead
public void channelRead(io.netty.channel.ChannelHandlerContext ctx, java.lang.Object msg)
- Specified by:
channelRead
in interfaceio.netty.channel.ChannelInboundHandler
- Overrides:
channelRead
in classio.netty.channel.ChannelInboundHandlerAdapter
-
channelReadComplete
public void channelReadComplete(io.netty.channel.ChannelHandlerContext ctx)
- Specified by:
channelReadComplete
in interfaceio.netty.channel.ChannelInboundHandler
- Overrides:
channelReadComplete
in classio.netty.channel.ChannelInboundHandlerAdapter
-
swapAndCopyCumulation
protected io.netty.buffer.ByteBuf swapAndCopyCumulation(io.netty.buffer.ByteBuf cumulation, io.netty.buffer.ByteBuf in)
Swap the existingcumulation
ByteBuf
for a newByteBuf
and copyin
. This method is called when a heuristic determines the amount of unused bytes is sufficiently high that a resize / defragmentation of the bytes fromcumulation
is beneficial.ByteBuf.discardReadBytes()
is generally avoided in this method because it changes the underlying data structure. If others have slices of thisByteBuf
their view on the data will become corrupted. This is commonly a problem when processing data asynchronously to avoid blocking theEventLoop
thread.- Parameters:
cumulation
- TheByteBuf
that accumulates across socket read operations.in
- The bytes to copy.- Returns:
- the result of the swap and copy operation.
-
cumulationReset
protected void cumulationReset()
Resets cumulation.
-
channelInactive
public void channelInactive(io.netty.channel.ChannelHandlerContext ctx)
- Specified by:
channelInactive
in interfaceio.netty.channel.ChannelInboundHandler
- Overrides:
channelInactive
in classio.netty.channel.ChannelInboundHandlerAdapter
-
userEventTriggered
public void userEventTriggered(io.netty.channel.ChannelHandlerContext ctx, java.lang.Object evt) throws java.lang.Exception
- Specified by:
userEventTriggered
in interfaceio.netty.channel.ChannelInboundHandler
- Overrides:
userEventTriggered
in classio.netty.channel.ChannelInboundHandlerAdapter
- Throws:
java.lang.Exception
-
decode
protected abstract void decode(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in) 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 data- Throws:
java.lang.Exception
- is thrown if an error occurs
-
decodeLast
protected void decodeLast(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in) 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)
but sub-classes may override this for some special cleanup operation.- Parameters:
ctx
- theChannelHandlerContext
which thisByteToMessageDecoder
belongs toin
- theByteBuf
from which to read data- Throws:
java.lang.Exception
- is thrown if an error occurs
-
-