The ProtocolCodecFilter uses an empty buffer internally as a sentinel
value to demarcate the end of a unit of input. If you don't return
that empty buffer, it keeps allocating additional space, which is
causing those huge buffers you're crashing on.

Your code shows some confusion about the difference between limit and
capacity, and this is what's messing up the empty buffers. Take a look
at the javadocs for java.nio.Buffer:
http://java.sun.com/javase/6/docs/api/java/nio/Buffer.html

...and pay close attention to the difference between capacity and
limit. Put simply, capacity indicates how much *can be* used, limit
indicates how much *is* used. Also, note the difference between flip()
and rewind(), one of which sets the value of limit to the current
position, while the other doesn't.

Going over the source code for your xor method (quoted with line numbers below):

line 2: allocate the new buffer to in.limit(), not to in.capacity()

line 5: your for loop is always reading one byte less than available
in the input, which you can fix by using i++" instead of "++i" in the
expression clause (or by changing the test clause to use ">=", but
this loop is deviant enough as it is). That said, it's a better idea
to avoid this altogether by using "while(in.hasRemaining())" as your
loop construct, because this avoids any kind of confusion about
whether you're counting bytes or elements (e.g. there are eight bytes
but only two ints in an IntBuffer of length 2).

lines 6-9: speaking of ints... you can xor bigger chunks at a time for
a nice speed boost (leave that for later on).
line 7: I like to use hexadecimal constants because each character
represents four bits, the underlying bit pattern is a lot easier to
see than with decimal constants.

line 11: return xor.flip() not xor.rewind(). In this particular case
they're equivalent (after fixing line 2), but if you ever copy a
partial buffer, they're quite different.

I suspect that if you fix lines 2, 5 and 11, your buffer data
exceptions will be history.

HTH

Barend


> 1   private ByteBuffer xor(ByteBuffer in) {
> 2       ByteBuffer xor = ByteBuffer.allocate(in.capacity());
> 3
> 4       // xor
> 5       for (int i = 0; i < in.limit(); ++i) {
> 6           byte b = in.get();
> 7           byte xbx = (byte) (b ^ 101);
> 8
> 9           xor = xor.put(xbx);
>10       }
>11
>11       return xor.rewind();
>12   }











On Thu, Oct 2, 2008 at 1:10 AM, Andres Quijano <[EMAIL PROTECTED]> wrote:
> Hi!
>
> I'm implementing a simple XORFilter to XOR encrypt my messages. I
> added the XORFilter on top of the ProtocolCodecFilter and it works ok,
> but even if the messages go from and to the server ok (it's a
> multiplayer game), I keep getting this error on background
>
> org.apache.mina.common.BufferDataException: dataLength: 1694498816
>        at 
> org.apache.mina.common.ByteBuffer.prefixedDataAvailable(ByteBuffer.java:1631)
>        at 
> org.apache.mina.filter.codec.serialization.ObjectSerializationDecoder.doDecode(ObjectSerializationDecoder.java:88)
>        at 
> org.apache.mina.filter.codec.CumulativeProtocolDecoder.decode(CumulativeProtocolDecoder.java:133)
>        at 
> org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:158)
>
> Some debugging showed that (quite possibly I'm wrong) this happens
> when the XORFilter encrypts an empty ByteBuffer that MINA sends
>
> Here is the source of the XORFilter class:
>
> public class XORFilter extends IoFilterAdapter {
>    @Override
>    public void messageReceived(NextFilter nextFilter, IoSession session,
>            Object message) throws Exception {
>
>        nextFilter.messageReceived(session, xor((ByteBuffer) message));
>    }
>
>    @Override
>    public void filterWrite(NextFilter nextFilter, IoSession session,
>            WriteRequest writeRequest) throws Exception {
>
>        ByteBuffer inBuffer = (ByteBuffer) writeRequest.getMessage();
>
>        nextFilter.filterWrite(session, new WriteRequest(xor(inBuffer),
>                writeRequest.getFuture()));
>    }
>
>    private ByteBuffer xor(ByteBuffer in) {
>        ByteBuffer xor = ByteBuffer.allocate(in.capacity());
>
>        // xor
>        for (int i = 0; i < in.limit(); ++i) {
>            byte b = in.get();
>            byte xbx = (byte) (b ^ 101);
>
>            xor = xor.put(xbx);
>        }
>
>        return xor.rewind();
>    }
> }
>
>
> Any ideas of what might be the cause? Also I'm new to "low level"
> byte-buffer handling, so any tips on improving the code will be most
> appreciated
>
> Thanks!
>
> Andres
>

Reply via email to