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
>>>>
>>>
>>
>