You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@mina.apache.org by Mikael Fernandus S <mi...@gmail.com> on 2011/09/01 06:48:59 UTC

Mina decoder issue: org.apache.mina.filter.codec.ProtocolDecoderException: java.lang.IllegalStateException: doDecode() can't return true when buffer is not consumed

Hi,

I am new to Mina so please bear with me if this issue is obvious. I
use Mina 1.1.7 and am developing a protocol codec that extends
DemuxingProtocolCodecFactory. What this codec does basicly is reading
the in buffer, validating the header and writing valid message to the
decoder output. This should be straightforward. However, when I tested
the codec, I got the following exception even though the codec
properly writes to the decoder oupt:

org.apache.mina.filter.codec.ProtocolDecoderException:
java.lang.IllegalStateException: doDecode() can't return true when
buffer is not consumed.

This error appears consistently for single buffer decoding process or
multiple buffer decoding process. I attach relevant source code below:

public class MyDecoder implements MessageDecoder {
    private messageLengthExists = false;
    private boolean multipleBuffer = false;
    private messageStartPosition = 0;
    private int bufferOffset = 0;
    private ByteBuffer msg = ByteBuffer.wrap(new byte[0]);
    private String error = null;

    public MessageDecoderResult decodable(IoSession, ByteBuffer in) {
        return readInputStreamHeader(in);
    }

    public MessagedecoderResult decode(IoSession session, ByteBuffer
in, ProtocolDecoderOutput out) throws Exception {
        if(error != null) {
            session.close();
            return MessageDecoderResult.NOT_OK;
        }
        if(messageLengthExists) {
                return decodeWithMessageLength(session, in, out);
        }
        return decodeWithoutMessageLength(session,in,out);
    }

    public MessageDecoderResult decodeWithMessageLength(IoSession
session, ByteBuffer in, ProtocolDecoderOutput out) {
        byte[] currentBytes = getBufferBytes(in);
        if(multipleBuffer) {
            int remaining = Math.min(msg.remaining(), in.remaining());
            if(remaining > 0) {
                msg.put(currentBytes,bufferOffset * (in.capacity() /
bufferOffset+1)) + messageStartPosition, (remaining -
messageStartPosition));
            }
            messageStartPosition = 0;
            currentBytes = null;
            if(msg.remaining() > 0) {
                 bufferOffset++;
                 return MessageDecoderResult.NEED_DATA;
            }
            else {
                out.write(msg);
                msg.clear();
                session.close();
                return MessageDecoderResult.OK;
            }
        }
        msg.put(currentBytes, messageStartPosition, (in.limit() -
messageStartPosition));
        out.write(msg);
        currentBytes = null;
        msg.clear();
        session.close();
        return MessageDecoderResult.OK;
    }

    private byte[] getBufferBytes(ByteBuffer in) {
        return getBufferBytes(in,0);
    }

    private byte[] getBufferBytes(ByteBuffer in, int startPosition) {
        byte[] mfsBytes = new byte[in.limit() - startPosition];
        int i = 0;
        while(i < (in.limit() - startPosition)) {
            byte b = in.get(startPosition + i);
            char c = (char) (b & 0xff);
            mfsBytes[i] = (byte) c;
            i++;
        }
        return mfsBytes;
    }

    ...
}

As a side note, i could not invoke the method in.array() and
in.arrayOffset(), which is pretty strange. I got
UnsupportedOperationException. By analyzing java.nio.ByteBuffer class,
I found that this is because the internal array hb is null.

Could anybody please show me what is not right with my approach above?

Thanks,
Mike

Re: Mina decoder issue: org.apache.mina.filter.codec.ProtocolDecoderException: java.lang.IllegalStateException: doDecode() can't return true when buffer is not consumed

Posted by Emmanuel Lecharny <el...@gmail.com>.
On 9/1/11 6:48 AM, Mikael Fernandus S wrote:
> Hi,
>
> I am new to Mina so please bear with me if this issue is obvious. I
> use Mina 1.1.7
I'm seriously enaging ypu to switch to MINA 2.0.4. MINA 1.1.7 is 
seriously lagging, and is probably not maintained anymore...

> and am developing a protocol codec that extends
> DemuxingProtocolCodecFactory. What this codec does basicly is reading
> the in buffer, validating the header and writing valid message to the
> decoder output. This should be straightforward. However, when I tested
> the codec, I got the following exception even though the codec
> properly writes to the decoder oupt:
>
> org.apache.mina.filter.codec.ProtocolDecoderException:
> java.lang.IllegalStateException: doDecode() can't return true when
> buffer is not consumed.
>
> This error appears consistently for single buffer decoding process or
> multiple buffer decoding process. I attach relevant source code below:
>
> public class MyDecoder implements MessageDecoder {
>      private messageLengthExists = false;
>      private boolean multipleBuffer = false;
>      private messageStartPosition = 0;
>      private int bufferOffset = 0;
>      private ByteBuffer msg = ByteBuffer.wrap(new byte[0]);
>      private String error = null;
>
>      public MessageDecoderResult decodable(IoSession, ByteBuffer in) {
>          return readInputStreamHeader(in);
>      }
>
>      public MessagedecoderResult decode(IoSession session, ByteBuffer
> in, ProtocolDecoderOutput out) throws Exception {
>          if(error != null) {
>              session.close();
>              return MessageDecoderResult.NOT_OK;
>          }
>          if(messageLengthExists) {
>                  return decodeWithMessageLength(session, in, out);
>          }
>          return decodeWithoutMessageLength(session,in,out);
>      }
>
>      public MessageDecoderResult decodeWithMessageLength(IoSession
> session, ByteBuffer in, ProtocolDecoderOutput out) {
>          byte[] currentBytes = getBufferBytes(in);
>          if(multipleBuffer) {
>              int remaining = Math.min(msg.remaining(), in.remaining());
>              if(remaining>  0) {
>                  msg.put(currentBytes,bufferOffset * (in.capacity() /
> bufferOffset+1)) + messageStartPosition, (remaining -
> messageStartPosition));
>              }
>              messageStartPosition = 0;
>              currentBytes = null;
>              if(msg.remaining()>  0) {
>                   bufferOffset++;
>                   return MessageDecoderResult.NEED_DATA;
>              }
>              else {
>                  out.write(msg);
>                  msg.clear();
>                  session.close();
>                  return MessageDecoderResult.OK;
>              }
>          }
>          msg.put(currentBytes, messageStartPosition, (in.limit() -
> messageStartPosition));
>          out.write(msg);
>          currentBytes = null;
>          msg.clear();
>          session.close();
>          return MessageDecoderResult.OK;
>      }
>
>      private byte[] getBufferBytes(ByteBuffer in) {
>          return getBufferBytes(in,0);
>      }
>
>      private byte[] getBufferBytes(ByteBuffer in, int startPosition) {
>          byte[] mfsBytes = new byte[in.limit() - startPosition];
>          int i = 0;
>          while(i<  (in.limit() - startPosition)) {
>              byte b = in.get(startPosition + i);
>              char c = (char) (b&  0xff);
>              mfsBytes[i] = (byte) c;
>              i++;
>          }
>          return mfsBytes;
>      }
>
>      ...
> }
>
> As a side note, i could not invoke the method in.array() and
> in.arrayOffset(), which is pretty strange. I got
> UnsupportedOperationException. By analyzing java.nio.ByteBuffer class,
> I found that this is because the internal array hb is null.
>
> Could anybody please show me what is not right with my approach above?
>
> Thanks,
> Mike
>


-- 
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com