AndrewBourgeois
AndrewBourgeois

Reputation: 2765

Netty 4: how to manually invoke handlers?

The situation: DelimiterBasedFrameDecoder extends ByteToMessageDecoder, and ByteToMessageDecoder does keep the unprocessed bytes in a ByteBuf called cumulation. I'd like to manually call this handler inside another handler to empty this cumulation ByteBuf.

What I tried:

DelimiterBasedFrameDecoder frameDecoder = (DelimiterBasedFrameDecoder) inboundChannel.pipeline().get("frameDecoder");
frameDecoder.channelRead(ctx, Unpooled.EMPTY_BUFFER);

The problem: What I tried doesn't work because there's no next handler so Netty tells me that the bytes are lost:

Discarded inbound message UnpooledHeapByteBuf(ridx: 0, widx: 57, cap: 57) that reached at the tail of the pipeline. Please check your pipeline configuration.

Upvotes: 0

Views: 1321

Answers (2)

AndrewBourgeois
AndrewBourgeois

Reputation: 2765

Norman put me on the right track but here's what I needed to do in my case:

PublicCumulationDelimiterBasedFrameDecoder frameDecoder = (PublicCumulationDelimiterBasedFrameDecoder) cp.get("frameDecoder");

ByteBuf bytesNotProcessed = frameDecoder.internalBuffer();

if (bytesNotProcessed != Unpooled.EMPTY_BUFFER) {                                   PublicCumulationDelimiterBasedFrameDecoder tmpDelimiterBasedFrameDecoder = new PublicCumulationDelimiterBasedFrameDecoder(2048, false, true, Unpooled.wrappedBuffer(new byte[] { 0x03 }));

    EmbeddedChannel ec = new EmbeddedChannel(tmpDelimiterBasedFrameDecoder, ... other handlers...);

    ByteBuf wrapper = Unpooled.buffer();
    wrapper.writeBytes(bytesNotProcessed);

    ec.writeInbound(wrapper);// make it process the bytes

    // put the remaining bytes (if any) back into the original buffer
    bytesNotProcessed.clear();
    bytesNotProcessed.writeBytes(tmpDelimiterBasedFrameDecoder.internalBuffer());
}

where PublicCumulationDelimiterBasedFrameDecoder is just this:

public class PublicCumulationDelimiterBasedFrameDecoder extends DelimiterBasedFrameDecoder {

    public PublicCumulationDelimiterBasedFrameDecoder(int maxFrameLength, boolean stripDelimiter, boolean failFast, ByteBuf delimiter) {
        super(maxFrameLength, stripDelimiter, failFast, delimiter);
    }

    public ByteBuf internalBuffer() {
        return super.internalBuffer();
    }
}

Upvotes: 0

Norman Maurer
Norman Maurer

Reputation: 23567

You can wrap your handler in a EmbeddedChannel and use writeInbound() and readInbound(). Check our unit tests for usage examples and also the javadocs.

Upvotes: 3

Related Questions