Latest version, with performance improvement:

private ByteBuffer xor(ByteBuffer in) {
    while (in.hasRemaining()) {
        if (in.remaining() >= 4) {
            int xor = in.getInt() ^ 0xAABBCCDD;
            in.position(in.position() - 4);
            in.putInt(xor);
        }
        else {
            byte xor = (byte) (in.get() ^ 0xEE);
            in.position(in.position() - 1);
            in.put(xor);
        }
    }

    return in.flip();
}

I don't like to read and then have to rewind the position like this...
is there another way? I couldn't find a peek method or something that
reads without modifying the position

On Thu, Oct 2, 2008 at 2:53 PM, Andres Quijano <[EMAIL PROTECTED]> wrote:
> Thanks a lot Barend, it was very useful
>
> I had it working before your message, it was a horrible mess, like this:
>
> private ByteBuffer xor(ByteBuffer in) {
>    ByteBuffer xor = ByteBuffer.allocate(in.capacity(), true);
>    xor.limit(in.limit());
>
>    int pos = in.position();
>
>    // xor
>    for (int i = 0; i < in.limit(); ++i) {
>        byte b = in.get();
>        byte xbx = (byte) (b ^ 101);
>
>        xor.put(xbx);
>    }
>
>    in.release();
>
>    xor.position(pos);
>
>    return xor;
> }
>
> After your suggestions I tried to do it in-place, this is what I came
> up with, it works, but it doesn't feel right... any hints?
>
> private ByteBuffer xor(ByteBuffer in) {
>    int i = 0;
>    while (in.hasRemaining()) {
>        in.put(i, (byte) (in.get(i) ^ 0x77));
>        in.position(++i);
>    }
>
>    return in.flip();
> }
>
> Thanks again
>
> Andres
>
> On Thu, Oct 2, 2008 at 2:16 PM, W.B. Garvelink
> <[EMAIL PROTECTED]> wrote:
>> The next step, of course, is to xor the bytes in place in the existing
>> buffer instead of allocating a second buffer, making a copy, and
>> deallocating the first. How would you do that?
>>
>>
>>
>> On Thu, Oct 2, 2008 at 7:06 PM, W.B. Garvelink
>> <[EMAIL PROTECTED]> wrote:
>>> 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