tossing exceptions on a couple more edgecases and additional tests on close

This commit is contained in:
Jesse McConnell 2012-06-28 16:32:50 -05:00
parent 9cd2f887d1
commit 153daf4f3b
4 changed files with 279 additions and 95 deletions

View File

@ -2,7 +2,6 @@ package org.eclipse.jetty.websocket.frames;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.OpCode;
@ -17,8 +16,6 @@ public class CloseFrame extends ControlFrame
public CloseFrame()
{
super(OpCode.CLOSE);
// no status code, no reason
setPayload(BufferUtil.EMPTY_BUFFER);
}
/**
@ -46,6 +43,11 @@ public class CloseFrame extends ControlFrame
throw new IllegalArgumentException("Status Codes must be in the range 1000 - 65535");
}
if ((reason != null) && (reason.length() > 123))
{
throw new IllegalArgumentException("Reason must not exceed 123 characters.");
}
byte utf[] = null;
int len = 2; // status code
if (StringUtil.isNotBlank(reason))

View File

@ -47,9 +47,9 @@ public class ClosePayloadParser extends FrameParser<CloseFrame>
/*
* invalid payload length.
*/
if (payloadLength == 1)
if ((payloadLength == 1) || (payloadLength > 125))
{
throw new WebSocketException("Close: invalid payload length: 1");
throw new WebSocketException("Close: invalid payload length: " + payloadLength);
}
if (payload == null)

View File

@ -4,19 +4,15 @@ import static org.hamcrest.Matchers.is;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.ByteBufferAssert;
import org.eclipse.jetty.websocket.Debug;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.CloseFrame;
import org.eclipse.jetty.websocket.frames.PingFrame;
import org.eclipse.jetty.websocket.frames.TextFrame;
import org.eclipse.jetty.websocket.generator.Generator;
import org.eclipse.jetty.websocket.parser.FrameParseCapture;
import org.eclipse.jetty.websocket.parser.Parser;
import org.eclipse.jetty.websocket.parser.PingPayloadParser;
import org.junit.Assert;
import org.junit.Test;
@ -24,6 +20,118 @@ public class TestABCase7_3
{
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
@Test (expected = WebSocketException.class)
public void testGenerate1BytePayloadCloseCase7_3_2()
{
CloseFrame pingFrame = new CloseFrame();
pingFrame.setPayload(new byte[] {0x00});
Generator generator = new Generator(policy);
ByteBuffer actual = ByteBuffer.allocate(32);
generator.generate(actual, pingFrame);
}
@Test
public void testGenerateCloseWithStatusCase7_3_3()
{
CloseFrame closeFrame = new CloseFrame(1000);
Generator generator = new Generator(policy);
ByteBuffer actual = ByteBuffer.allocate(32);
generator.generate(actual, closeFrame);
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 });
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testGenerateCloseWithStatusMaxReasonCase7_3_5()
{
StringBuilder message = new StringBuilder();
for ( int i = 0 ; i < 123 ; ++i )
{
message.append("*");
}
byte[] messageBytes = message.toString().getBytes();
CloseFrame closeFrame = new CloseFrame(1000, message.toString());
Generator generator = new Generator(policy);
ByteBuffer actual = ByteBuffer.allocate(132);
generator.generate(actual, closeFrame);
ByteBuffer expected = ByteBuffer.allocate(132);
expected.put(new byte[]
{ (byte)0x88 });
byte b = 0x00; // no masking
b |= (messageBytes.length + 2) & 0x7F;
expected.put(b);
expected.putShort((short)1000);
expected.put(messageBytes);
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test (expected = IllegalArgumentException.class )
public void testGenerateCloseWithStatusMaxReasonCase7_3_6()
{
StringBuilder message = new StringBuilder();
for ( int i = 0 ; i < 124 ; ++i )
{
message.append("*");
}
byte[] messageBytes = message.toString().getBytes();
CloseFrame closeFrame = new CloseFrame(1000, message.toString());
}
@Test
public void testGenerateCloseWithStatusReasonCase7_3_4()
{
String message = "bad cough";
byte[] messageBytes = message.getBytes();
CloseFrame closeFrame = new CloseFrame(1000, message);
Generator generator = new Generator(policy);
ByteBuffer actual = ByteBuffer.allocate(32);
generator.generate(actual, closeFrame);
ByteBuffer expected = ByteBuffer.allocate(32);
expected.put(new byte[]
{ (byte)0x88 });
byte b = 0x00; // no masking
b |= (message.length() + 2) & 0x7F;
expected.put(b);
expected.putShort((short)1000);
expected.put(messageBytes);
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testGenerateEmptyCloseCase7_3_1()
{
@ -44,41 +152,6 @@ public class TestABCase7_3
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testParseEmptyCloseCase7_3_1()
{
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x88, (byte)0x00 });
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(CloseFrame.class,1);
CloseFrame pActual = (CloseFrame)capture.getFrames().get(0);
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0));
ByteBufferAssert.assertSize("CloseFrame.payload",0,pActual.getPayload());
}
@Test (expected = WebSocketException.class)
public void testGenerate1BytePayloadCloseCase7_3_2()
{
CloseFrame pingFrame = new CloseFrame();
pingFrame.setPayload(new byte[] {0x00});
Generator generator = new Generator(policy);
ByteBuffer actual = ByteBuffer.allocate(32);
generator.generate(actual, pingFrame);
}
@Test
public void testParse1BytePayloadCloseCase7_3_2()
@ -105,27 +178,137 @@ public class TestABCase7_3
}
@Test
public void testGenerateCloseWithStatusCase7_3_3()
public void testParseCloseWithStatusCase7_3_3()
{
CloseFrame closeFrame = new CloseFrame(1000);
Generator generator = new Generator(policy);
ByteBuffer actual = ByteBuffer.allocate(32);
generator.generate(actual, closeFrame);
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 });
actual.flip();
expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(CloseFrame.class,1);
CloseFrame pActual = (CloseFrame)capture.getFrames().get(0);
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(2));
ByteBufferAssert.assertSize("CloseFrame.payload",2,pActual.getPayload());
}
@Test
public void testParseCloseWithStatusMaxReasonCase7_3_5()
{
StringBuilder message = new StringBuilder();
for ( int i = 0 ; i < 123 ; ++i )
{
message.append("*");
}
byte[] messageBytes = message.toString().getBytes();
ByteBuffer expected = ByteBuffer.allocate(132);
expected.put(new byte[]
{ (byte)0x88 });
byte b = 0x00; // no masking
b |= (messageBytes.length + 2) & 0x7F;
expected.put(b);
expected.putShort((short)1000);
expected.put(messageBytes);
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(CloseFrame.class,1);
CloseFrame pActual = (CloseFrame)capture.getFrames().get(0);
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(125));
ByteBufferAssert.assertSize("CloseFrame.payload", 125,pActual.getPayload());
}
@Test
public void testParseCloseWithStatusCase7_3_3()
public void testParseCloseWithStatusMaxReasonCase7_3_6()
{
StringBuilder message = new StringBuilder();
for ( int i = 0 ; i < 124 ; ++i )
{
message.append("*");
}
byte[] messageBytes = message.toString().getBytes();
ByteBuffer expected = ByteBuffer.allocate(132);
expected.put(new byte[]
{ (byte)0x88 });
byte b = 0x00; // no masking
b |= (messageBytes.length + 2) & 0x7F;
expected.put(b);
expected.putShort((short)1000);
expected.put(messageBytes);
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
Assert.assertEquals( "error on invalid close payload", 1, capture.getErrorCount(WebSocketException.class)) ;
WebSocketException known = capture.getErrors().get(0);
Assert.assertTrue("invalid payload should be in message",known.getMessage().contains("invalid payload length"));
}
@Test
public void testParseCloseWithStatusReasonCase7_3_4()
{
String message = "bad cough";
byte[] messageBytes = message.getBytes();
ByteBuffer expected = ByteBuffer.allocate(32);
expected.put(new byte[]
{ (byte)0x88 });
byte b = 0x00; // no masking
b |= (messageBytes.length + 2) & 0x7F;
expected.put(b);
expected.putShort((short)1000);
expected.put(messageBytes);
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors();
capture.assertHasFrame(CloseFrame.class,1);
CloseFrame pActual = (CloseFrame)capture.getFrames().get(0);
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(messageBytes.length + 2));
ByteBufferAssert.assertSize("CloseFrame.payload",messageBytes.length + 2,pActual.getPayload());
}
@Test
public void testParseEmptyCloseCase7_3_1()
{
ByteBuffer expected = ByteBuffer.allocate(5);
@ -147,5 +330,4 @@ public class TestABCase7_3
ByteBufferAssert.assertSize("CloseFrame.payload",0,pActual.getPayload());
}
}