Adding ClosePayloadParser & Tests
This commit is contained in:
parent
b61a58ad64
commit
1692b4f7c2
|
@ -8,7 +8,7 @@ import org.eclipse.jetty.websocket.api.WebSocket;
|
|||
*/
|
||||
public class CloseFrame extends ControlFrame
|
||||
{
|
||||
private final short statusCode;
|
||||
private short statusCode;
|
||||
private String reason;
|
||||
|
||||
public CloseFrame()
|
||||
|
@ -43,6 +43,11 @@ public class CloseFrame extends ControlFrame
|
|||
this.reason = reason;
|
||||
}
|
||||
|
||||
public void setStatusCode(short statusCode)
|
||||
{
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.eclipse.jetty.websocket.parser;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.frames.CloseFrame;
|
||||
|
||||
|
@ -11,6 +13,8 @@ import org.eclipse.jetty.websocket.frames.CloseFrame;
|
|||
public class ClosePayloadParser extends FrameParser<CloseFrame>
|
||||
{
|
||||
private CloseFrame frame;
|
||||
private ByteBuffer payload;
|
||||
private int payloadLength;
|
||||
|
||||
public ClosePayloadParser(WebSocketPolicy policy)
|
||||
{
|
||||
|
@ -34,7 +38,35 @@ public class ClosePayloadParser extends FrameParser<CloseFrame>
|
|||
@Override
|
||||
public boolean parsePayload(ByteBuffer buffer)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
payloadLength = getFrame().getPayloadLength();
|
||||
if (payloadLength == 0)
|
||||
{
|
||||
// no status code. no reason.
|
||||
return true;
|
||||
}
|
||||
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
if (payload == null)
|
||||
{
|
||||
getPolicy().assertValidBinaryMessageSize(payloadLength);
|
||||
payload = ByteBuffer.allocate(payloadLength);
|
||||
}
|
||||
|
||||
copyBuffer(buffer,payload,payload.remaining());
|
||||
|
||||
if (payload.position() >= payloadLength)
|
||||
{
|
||||
payload.flip();
|
||||
frame.setStatusCode(payload.getShort());
|
||||
if (payload.remaining() > 0)
|
||||
{
|
||||
String reason = BufferUtil.toString(payload,StringUtil.__UTF8_CHARSET);
|
||||
frame.setReason(reason);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,13 @@ public class Parser
|
|||
boolean rsv1 = ((b & 0x40) != 0);
|
||||
boolean rsv2 = ((b & 0x20) != 0);
|
||||
boolean rsv3 = ((b & 0x10) != 0);
|
||||
OpCode opcode = OpCode.from((byte)(b & 0x0F));
|
||||
byte opc = (byte)(b & 0x0F);
|
||||
OpCode opcode = OpCode.from(opc);
|
||||
|
||||
if (opcode == null)
|
||||
{
|
||||
throw new WebSocketException("Unknown opcode: " + opc);
|
||||
}
|
||||
|
||||
if (opcode.isControlFrame() && !fin)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.websocket.Debug;
|
||||
import org.eclipse.jetty.websocket.api.WebSocket;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.frames.CloseFrame;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ClosePayloadParserTest
|
||||
{
|
||||
@Test
|
||||
public void testGameOver()
|
||||
{
|
||||
Debug.enableDebugLogging(Parser.class);
|
||||
Debug.enableDebugLogging(ClosePayloadParser.class);
|
||||
String expectedReason = "Game Over";
|
||||
|
||||
byte utf[] = expectedReason.getBytes(StringUtil.__UTF8_CHARSET);
|
||||
ByteBuffer payload = ByteBuffer.allocate(utf.length + 2);
|
||||
payload.putShort(WebSocket.CLOSE_NORMAL);
|
||||
payload.put(utf,0,utf.length);
|
||||
payload.flip();
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(24);
|
||||
buf.put((byte)(0x80 | 0x08)); // fin + close
|
||||
buf.put((byte)(0x80 | payload.remaining()));
|
||||
MaskedByteBuffer.putMask(buf);
|
||||
MaskedByteBuffer.putPayload(buf,payload);
|
||||
buf.flip();
|
||||
|
||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||
Parser parser = new Parser(policy);
|
||||
FrameParseCapture capture = new FrameParseCapture();
|
||||
parser.addListener(capture);
|
||||
parser.parse(buf);
|
||||
|
||||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(CloseFrame.class,1);
|
||||
CloseFrame txt = (CloseFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("CloseFrame.statusCode",txt.getStatusCode(),is(WebSocket.CLOSE_NORMAL));
|
||||
Assert.assertThat("CloseFrame.data",txt.getReason(),is(expectedReason));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class MaskedByteBuffer
|
||||
{
|
||||
private static byte[] mask = new byte[]
|
||||
{ 0x00, (byte)0xF0, 0x0F, (byte)0xFF };
|
||||
|
||||
public static void putMask(ByteBuffer buffer)
|
||||
{
|
||||
buffer.put(mask,0,mask.length);
|
||||
}
|
||||
|
||||
public static void putPayload(ByteBuffer buffer, byte[] payload)
|
||||
{
|
||||
int len = payload.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
buffer.put((byte)(payload[i] ^ mask[i % 4]));
|
||||
}
|
||||
}
|
||||
|
||||
public static void putPayload(ByteBuffer buffer, ByteBuffer payload)
|
||||
{
|
||||
int len = payload.remaining();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
buffer.put((byte)(payload.get() ^ mask[i % 4]));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,11 +16,8 @@ import org.junit.Test;
|
|||
|
||||
public class TextPayloadParserTest
|
||||
{
|
||||
private final byte[] mask = new byte[]
|
||||
{ 0x00, (byte)0xF0, 0x0F, (byte)0xFF };
|
||||
|
||||
@Test
|
||||
public void testFrameTooLargeDueToPolicyText() throws Exception
|
||||
public void testFrameTooLargeDueToPolicy() throws Exception
|
||||
{
|
||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||
policy.setMaxTextMessageSize(1024); // set policy
|
||||
|
@ -33,8 +30,8 @@ public class TextPayloadParserTest
|
|||
buf.put((byte)0x81);
|
||||
buf.put((byte)(0x80 | 0x7E)); // 0x7E == 126 (a 2 byte payload length)
|
||||
buf.putShort((short)utf.length);
|
||||
writeMask(buf);
|
||||
writeMaskedPayload(buf,utf);
|
||||
MaskedByteBuffer.putMask(buf);
|
||||
MaskedByteBuffer.putPayload(buf,utf);
|
||||
buf.flip();
|
||||
|
||||
Parser parser = new Parser(policy);
|
||||
|
@ -68,8 +65,8 @@ public class TextPayloadParserTest
|
|||
buf.put((byte)0x81);
|
||||
buf.put((byte)(0x80 | 0x7F)); // 0x7F == 127 (a 4 byte payload length)
|
||||
buf.putInt(utf.length);
|
||||
writeMask(buf);
|
||||
writeMaskedPayload(buf,utf);
|
||||
MaskedByteBuffer.putMask(buf);
|
||||
MaskedByteBuffer.putPayload(buf,utf);
|
||||
buf.flip();
|
||||
|
||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||
|
@ -103,8 +100,8 @@ public class TextPayloadParserTest
|
|||
buf.put((byte)0x81);
|
||||
buf.put((byte)(0x80 | 0x7E)); // 0x7E == 126 (a 2 byte payload length)
|
||||
buf.putShort((short)utf.length);
|
||||
writeMask(buf);
|
||||
writeMaskedPayload(buf,utf);
|
||||
MaskedByteBuffer.putMask(buf);
|
||||
MaskedByteBuffer.putPayload(buf,utf);
|
||||
buf.flip();
|
||||
|
||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||
|
@ -133,14 +130,14 @@ public class TextPayloadParserTest
|
|||
// part 1
|
||||
buf.put((byte)0x01); // no fin + text
|
||||
buf.put((byte)(0x80 | b1.length));
|
||||
writeMask(buf);
|
||||
writeMaskedPayload(buf,b1);
|
||||
MaskedByteBuffer.putMask(buf);
|
||||
MaskedByteBuffer.putPayload(buf,b1);
|
||||
|
||||
// part 2
|
||||
buf.put((byte)0x80); // fin + continuation
|
||||
buf.put((byte)(0x80 | b2.length));
|
||||
writeMask(buf);
|
||||
writeMaskedPayload(buf,b2);
|
||||
MaskedByteBuffer.putMask(buf);
|
||||
MaskedByteBuffer.putPayload(buf,b2);
|
||||
|
||||
buf.flip();
|
||||
|
||||
|
@ -162,12 +159,13 @@ public class TextPayloadParserTest
|
|||
public void testShortMaskedText() throws Exception
|
||||
{
|
||||
String expectedText = "Hello World";
|
||||
byte utf[] = expectedText.getBytes(StringUtil.__UTF8_CHARSET);
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(24);
|
||||
buf.put((byte)0x81);
|
||||
buf.put((byte)(0x80 | expectedText.length()));
|
||||
writeMask(buf);
|
||||
writeMaskedPayload(buf,expectedText.getBytes(StringUtil.__UTF8));
|
||||
buf.put((byte)(0x80 | utf.length));
|
||||
MaskedByteBuffer.putMask(buf);
|
||||
MaskedByteBuffer.putPayload(buf,utf);
|
||||
buf.flip();
|
||||
|
||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||
|
@ -192,8 +190,8 @@ public class TextPayloadParserTest
|
|||
ByteBuffer buf = ByteBuffer.allocate(24);
|
||||
buf.put((byte)0x81);
|
||||
buf.put((byte)(0x80 | utf.length));
|
||||
writeMask(buf);
|
||||
writeMaskedPayload(buf,utf);
|
||||
MaskedByteBuffer.putMask(buf);
|
||||
MaskedByteBuffer.putPayload(buf,utf);
|
||||
buf.flip();
|
||||
|
||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||
|
@ -207,18 +205,4 @@ public class TextPayloadParserTest
|
|||
TextFrame txt = (TextFrame)capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.data",txt.getData().toString(),is(expectedText));
|
||||
}
|
||||
|
||||
private void writeMask(ByteBuffer buf)
|
||||
{
|
||||
buf.put(mask,0,mask.length);
|
||||
}
|
||||
|
||||
private void writeMaskedPayload(ByteBuffer buf, byte[] bytes)
|
||||
{
|
||||
int len = bytes.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
buf.put((byte)(bytes[i] ^ mask[i % 4]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue