protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
        if (lineBasedDecoder != null) {
            return lineBasedDecoder.decode(ctx, buffer);
        }
        // Try all delimiters and choose the delimiter which yields the shortest frame.
        int minFrameLength = Integer.MAX_VALUE;
        ByteBuf minDelim = null;
        for (ByteBuf delim : delimiters) {
            int frameLength = indexOf(buffer, delim);
            if (frameLength >= 0 && frameLength < minFrameLength) {
                minFrameLength = frameLength;
                minDelim = delim;
            }
        }

        if (minDelim != null) {
            int minDelimLength = minDelim.capacity();
            ByteBuf frame;

            if (discardingTooLongFrame) {
                // We've just finished discarding a very large frame.
                // Go back to the initial state.
                discardingTooLongFrame = false;
                buffer.skipBytes(minFrameLength + minDelimLength);

                int tooLongFrameLength = this.tooLongFrameLength;
                this.tooLongFrameLength = 0;
                if (!failFast) {
                    fail(tooLongFrameLength);
                }
                return null;
            }

            if (minFrameLength > maxFrameLength) {
                // Discard read frame.
                buffer.skipBytes(minFrameLength + minDelimLength);
                fail(minFrameLength);
                return null;
            }

            if (stripDelimiter) {
                frame = buffer.readRetainedSlice(minFrameLength);
                buffer.skipBytes(minDelimLength);
            } else {
                frame = buffer.readRetainedSlice(minFrameLength + minDelimLength);
            }

            return frame;
        } else if (emitLastLineWithoutDelimiter && !ctx.channel().isActive()) {
            minFrameLength = buffer.readableBytes();
            ByteBuf frame;

            if (discardingTooLongFrame) {
                // We've just finished discarding a very large frame.
                // Go back to the initial state.
                discardingTooLongFrame = false;
                buffer.skipBytes(minFrameLength);

                int tooLongFrameLength = this.tooLongFrameLength;
                this.tooLongFrameLength = 0;
                if (!failFast) {
                    fail(tooLongFrameLength);
                }
                return null;
            }

            if (minFrameLength > maxFrameLength) {
                // Discard read frame.
                buffer.skipBytes(minFrameLength);
                fail(minFrameLength);
                return null;
            }

            frame = buffer.readRetainedSlice(minFrameLength);

            return frame;
        } else {
            if (!discardingTooLongFrame) {
                if (buffer.readableBytes() > maxFrameLength) {
                    // Discard the content of the buffer until a delimiter is found.
                    tooLongFrameLength = buffer.readableBytes();
                    buffer.skipBytes(buffer.readableBytes());
                    discardingTooLongFrame = true;
                    if (failFast) {
                        fail(tooLongFrameLength);
                    }
                }
            } else {
                // Still discarding the buffer since a delimiter is not found.
                tooLongFrameLength += buffer.readableBytes();
                buffer.skipBytes(buffer.readableBytes());
            }
            return null;
        }
    }
protected Object decode ( ChannelHandlerContext ctx , ByteBuf buffer ) throws Exception { if ( lineBasedDecoder != null ) { return lineBasedDecoder . decode ( ctx , buffer ) ; } int minFrameLength = Integer . MAX_VALUE ; ByteBuf minDelim = null ; for ( ByteBuf delim : delimiters ) { int frameLength = indexOf ( buffer , delim ) ; if ( frameLength >= 0 && frameLength < minFrameLength ) { minFrameLength = frameLength ; minDelim = delim ; } } if ( minDelim != null ) { int minDelimLength = minDelim . capacity ( ) ; ByteBuf frame ; if ( discardingTooLongFrame ) { discardingTooLongFrame = false ; buffer . skipBytes ( minFrameLength + minDelimLength ) ; int tooLongFrameLength = this . tooLongFrameLength ; this . tooLongFrameLength = 0 ; if ( ! failFast ) { fail ( tooLongFrameLength ) ; } return null ; } if ( minFrameLength > maxFrameLength ) { buffer . skipBytes ( minFrameLength + minDelimLength ) ; fail ( minFrameLength ) ; return null ; } if ( stripDelimiter ) { frame = buffer . readRetainedSlice ( minFrameLength ) ; buffer . skipBytes ( minDelimLength ) ; } else { frame = buffer . readRetainedSlice ( minFrameLength + minDelimLength ) ; } return frame ; } else if ( emitLastLineWithoutDelimiter && ! ctx . channel ( ) . isActive ( ) ) { minFrameLength = buffer . readableBytes ( ) ; ByteBuf frame ; if ( discardingTooLongFrame ) { discardingTooLongFrame = false ; buffer . skipBytes ( minFrameLength ) ; int tooLongFrameLength = this . tooLongFrameLength ; this . tooLongFrameLength = 0 ; if ( ! failFast ) { fail ( tooLongFrameLength ) ; } return null ; } if ( minFrameLength > maxFrameLength ) { buffer . skipBytes ( minFrameLength ) ; fail ( minFrameLength ) ; return null ; } frame = buffer . readRetainedSlice ( minFrameLength ) ; return frame ; } else { if ( ! discardingTooLongFrame ) { if ( buffer . readableBytes ( ) > maxFrameLength ) { tooLongFrameLength = buffer . readableBytes ( ) ; buffer . skipBytes ( buffer . readableBytes ( ) ) ; discardingTooLongFrame = true ; if ( failFast ) { fail ( tooLongFrameLength ) ; } } } else { tooLongFrameLength += buffer . readableBytes ( ) ; buffer . skipBytes ( buffer . readableBytes ( ) ) ; } return null ; } }
Create a frame out of the {@link ByteBuf} and return it.

@param ctx    the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to
@param buffer the {@link ByteBuf} from which to read data
@return frame           the {@link ByteBuf} which represent the frame or {@code null} if no frame could
be created.