I am using the EmbeddedChannel
to test my handlers
and codecs
to process messages in the following format:
+------------+------------------+----------------+
| Header | Payload Length | Payload |
| 16 bytes | 2 bytes | "Some data" |
+------------+------------------+----------------+
Firstly, what I want to achieve:
- Process first 16 bytes by creating an object to store the header details in and add the decoded header object to the
AttributeMap
of theChannelHandlerContext
for later use; - Wait for/retrieve entire payload data;
- Have Header object and entire payload as
ByteBuf
available on final handler to route message.
I using the following handlers:
ByteToMessageCodec<ByteBuf>
to extract the header info and add it to the attribute list.LengthFieldBasedFrameDecoder
to read the payload length and wait for/retrieve entire frame.SimpleChannelInboundHandler
that will use the header object retrieved from attribute list to route the payload accordingly.
When a message is passed to the decode
method of the ByteToMessageCodec
, the header is processed and extracted correctly. I then continue to add the Header object to the AttributeMap
and add the ByteBuf
(which has a readableBytes = 2 bytes (payload lenght indicator) + payload length).
Let's say the payload length is 1020 bytes. The message is initially received by the codec
will have readableBytes = 16 bytes + 2 bytes + 1020 bytes
. The header is read by the decode
method and the remainder of the available bytes (1022) is then added to the List<Object> out
.
If my understanding is correct, the remainder of the bytes will now be passed to the next handler which is LengthFieldBasedFrameDecoder
which will read the length indicator and pass the payload (1020 bytes) to the SimpleChannelHanlder
, but I must be mistaken.
The decode
method is called again, with the same 1022 bytes that was added to the List<Object> out
.
In the JavaDoc of the decode method there is the following:
Decode the from one ByteBuf to an other. This method will be called till either the input ByteBuf
has nothing to read when return from this method or till nothing was read from the input ByteBuf.
Does this mean decode
will be called until readableBytes == 0
?
What will be the most efficient way to pass the rest of the message to the LengthFieldBasedFrameDecoder
?
I assume the LengthFieldBasedFrameDecoder
needs a ByteBuf
as input, so does this mean I need to set the readerIndex = 0
and add a copy of the ByteBuf to the List<Object> out
?
Any help/advice/criticism will be appreciated, I want to do this in the cleanest way possible.
Here is my decode
method:
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
byte [] headerBytes = new byte[HEADER_LENGTH];
in.readBytes(headerBytes, 0, HEADER_LENGTH);
Header header = new Header(headerBytes);
System.out.println("Decoded Header: \n" + header);
//Set the header attribute so it can be used by routing handlers
ctx.attr(ChannelAttributes.HEADER).getAndSet(header);
//pass to next handler
out.add(in);
}
NOTE: I'm reading Netty in Action MEAP v8