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