Improved masking performance by using ints instead of bytes.

This commit is contained in:
Simone Bordet 2013-08-19 22:11:52 +02:00
parent 1c73ce674f
commit 45724b63ec
3 changed files with 39 additions and 31 deletions

View File

@ -282,24 +282,29 @@ public class Generator
{
byte[] mask = frame.getMask();
buffer.put(mask);
int maskInt = ByteBuffer.wrap(mask).getInt();
// perform data masking here
byte mb;
ByteBuffer payload = frame.getPayload();
if ((payload != null) && (payload.remaining() > 0))
{
int pos = payload.position();
int limit = payload.limit();
for (int i = pos; i < limit; i++)
int maskOffset = 0;
int start = payload.position();
int end = payload.limit();
int remaining;
while ((remaining = end - start) > 0)
{
// get raw byte from buffer.
mb = payload.get(i);
// mask, using offset information from frame windowing.
mb ^= mask[(i - pos) % 4];
// Mask each byte by its absolute position in the payload bytebuffer
payload.put(i,mb);
if (remaining >= 4)
{
payload.putInt(start, payload.getInt(start) ^ maskInt);
start += 4;
}
else
{
payload.put(start, (byte)(payload.get(start) ^ mask[maskOffset & 3]));
++start;
++maskOffset;
}
}
}
}

View File

@ -24,39 +24,42 @@ import org.eclipse.jetty.websocket.api.extensions.Frame;
public class DeMaskProcessor implements PayloadProcessor
{
private boolean isMasked;
private byte mask[];
private int offset;
private byte maskBytes[];
private int maskOffset;
@Override
public void process(ByteBuffer payload)
{
if (!isMasked)
if (maskBytes == null)
{
return;
}
int maskInt = ByteBuffer.wrap(maskBytes).getInt();
int start = payload.position();
int end = payload.limit();
for (int i = start; i < end; i++, offset++)
int offset = this.maskOffset;
int remaining;
while ((remaining = end - start) > 0)
{
payload.put(i,(byte)(payload.get(i) ^ mask[offset % 4]));
if (remaining >= 4 && offset == 0)
{
payload.putInt(start, payload.getInt(start) ^ maskInt);
start +=4;
}
else
{
payload.put(start, (byte)(payload.get(start) ^ maskBytes[offset & 3]));
++start;
++offset;
}
}
}
@Override
public void reset(Frame frame)
{
this.isMasked = frame.isMasked();
if (isMasked)
{
this.mask = frame.getMask();
}
else
{
this.mask = null;
}
offset = 0;
this.maskBytes = frame.isMasked() ? frame.getMask() : null;
this.maskOffset = 0;
}
}

View File

@ -27,7 +27,6 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.UnitGenerator;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.io.payload.DeMaskProcessor;
import org.junit.Test;
public class DeMaskProcessorTest
@ -37,7 +36,8 @@ public class DeMaskProcessorTest
@Test
public void testDeMaskText()
{
String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
// Use a string that is not multiple of 4 in length to test if/else branches in DeMaskProcessor
String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF01";
WebSocketFrame frame = WebSocketFrame.text(message);
frame.setMask(TypeUtil.fromHexString("11223344"));