@Override
    public void decode(IoSession session, IoBuffer in,
                       ProtocolDecoderOutput out) throws Exception {

        IoBufferEx inEx = (IoBufferEx) in;

        if (!session.getTransportMetadata().hasFragmentation()) {
            while (in.hasRemaining()) {
                if (!doDecode(session, inEx, out)) {
                    break;
                }
            }

            return;
        }

        boolean usingSessionBuffer = true;
        IoBufferEx buf = (IoBufferEx) session.getAttribute(BUFFER);
        // If we have a session buffer, append data to that; otherwise
        // use the buffer read from the network directly.
        if (buf != null) {
            boolean appended = false;
            // Make sure that the buffer is auto-expanded.
            if (buf.isAutoExpand()) {
                try {
                    buf.put(inEx);
                    appended = true;
                } catch (IllegalStateException e) {
                    // A user called derivation method (e.g. slice()),
                    // which disables auto-expansion of the parent buffer.
                } catch (IndexOutOfBoundsException e) {
                    // A user disabled auto-expansion.
                }
            }

            if (appended) {
                buf.flip();
            } else {
                // Reallocate the buffer if append operation failed due to
                // derivation or disabled auto-expansion.
                buf.flip();

                ByteBuffer newNioBuf = allocator.allocate(buf.remaining() + in.remaining());
                IoBufferEx newBuf = allocator.wrap(newNioBuf).setAutoExpander(allocator);
                newBuf.order(buf.order());
                newBuf.put(buf);
                newBuf.put(inEx);
                newBuf.flip();
                buf = newBuf;

                // Update the session attribute.
                session.setAttribute(BUFFER, buf);
            }
        } else {
            buf = inEx;
            usingSessionBuffer = false;
        }

        for (;;) {
            int oldPos = buf.position();
            boolean decoded = doDecode(session, buf, out);
            if (decoded) {
                if (buf.position() == oldPos) {
                    throw new IllegalStateException(
                            "doDecode() can't return true when buffer is not consumed.");
                }

                if (!buf.hasRemaining()) {
                    break;
                }
            } else {
                break;
            }
        }

        // if there is any data left that cannot be decoded, we store
        // it in a buffer in the session and next time this decoder is
        // invoked the session buffer gets appended to
        if (buf.hasRemaining()) {
                storeRemainingInSession(buf, session);
        } else {
            if (usingSessionBuffer) {
                removeSessionBuffer(session);
            }
        }
    }
@ Override public void decode ( IoSession session , IoBuffer in , ProtocolDecoderOutput out ) throws Exception { IoBufferEx inEx = ( IoBufferEx ) in ; if ( ! session . getTransportMetadata ( ) . hasFragmentation ( ) ) { while ( in . hasRemaining ( ) ) { if ( ! doDecode ( session , inEx , out ) ) { break ; } } return ; } boolean usingSessionBuffer = true ; IoBufferEx buf = ( IoBufferEx ) session . getAttribute ( BUFFER ) ; if ( buf != null ) { boolean appended = false ; if ( buf . isAutoExpand ( ) ) { try { buf . put ( inEx ) ; appended = true ; } catch ( IllegalStateException e ) { } catch ( IndexOutOfBoundsException e ) { } } if ( appended ) { buf . flip ( ) ; } else { buf . flip ( ) ; ByteBuffer newNioBuf = allocator . allocate ( buf . remaining ( ) + in . remaining ( ) ) ; IoBufferEx newBuf = allocator . wrap ( newNioBuf ) . setAutoExpander ( allocator ) ; newBuf . order ( buf . order ( ) ) ; newBuf . put ( buf ) ; newBuf . put ( inEx ) ; newBuf . flip ( ) ; buf = newBuf ; session . setAttribute ( BUFFER , buf ) ; } } else { buf = inEx ; usingSessionBuffer = false ; } for ( ; ; ) { int oldPos = buf . position ( ) ; boolean decoded = doDecode ( session , buf , out ) ; if ( decoded ) { if ( buf . position ( ) == oldPos ) { throw new IllegalStateException ( "doDecode() can't return true when buffer is not consumed." ) ; } if ( ! buf . hasRemaining ( ) ) { break ; } } else { break ; } } if ( buf . hasRemaining ( ) ) { storeRemainingInSession ( buf , session ) ; } else { if ( usingSessionBuffer ) { removeSessionBuffer ( session ) ; } } }
Cumulates content of <tt>in</tt> into internal buffer and forwards
decoding request to {@link #doDecode(IoSession, IoBuffer, ProtocolDecoderOutput)}.
<tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt>
and the cumulative buffer is compacted after decoding ends.

@throws IllegalStateException if your <tt>doDecode()</tt> returned
<tt>true</tt> not consuming the cumulative buffer.