Merge branch 'jetty-9' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project into jetty-9

This commit is contained in:
Joakim Erdfelt 2012-06-28 15:30:46 -07:00
commit 54399545b1
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 java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.OpCode; import org.eclipse.jetty.websocket.api.OpCode;
@ -17,8 +16,6 @@ public class CloseFrame extends ControlFrame
public CloseFrame() public CloseFrame()
{ {
super(OpCode.CLOSE); 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"); 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; byte utf[] = null;
int len = 2; // status code int len = 2; // status code
if (StringUtil.isNotBlank(reason)) if (StringUtil.isNotBlank(reason))

View File

@ -20,10 +20,10 @@ public class CloseFrameGenerator extends FrameGenerator<CloseFrame>
if ( close.getStatusCode() != 0 ) if ( close.getStatusCode() != 0 )
{ {
buffer.putChar((char)close.getStatusCode()); // char is unsigned 16 buffer.putChar((char)close.getStatusCode()); // char is unsigned 16
// payload requires a status code in order to be written // payload requires a status code in order to be written
if ( close.hasPayload() ) if ( close.hasPayload() )
{ {
if (close.hasReason()) if (close.hasReason())
{ {
byte utf[] = close.getReason().getBytes(StringUtil.__UTF8_CHARSET); byte utf[] = close.getReason().getBytes(StringUtil.__UTF8_CHARSET);
@ -31,7 +31,7 @@ public class CloseFrameGenerator extends FrameGenerator<CloseFrame>
} }
} }
} }
else if ( close.hasPayload() ) else if (close.hasPayload())
{ {
throw new WebSocketException("Close frames require setting a status code if using payload."); throw new WebSocketException("Close frames require setting a status code if using payload.");
} }

View File

@ -47,9 +47,9 @@ public class ClosePayloadParser extends FrameParser<CloseFrame>
/* /*
* invalid payload length. * 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) if (payload == null)

View File

@ -4,19 +4,15 @@ import static org.hamcrest.Matchers.is;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.ByteBufferAssert; import org.eclipse.jetty.websocket.ByteBufferAssert;
import org.eclipse.jetty.websocket.Debug; import org.eclipse.jetty.websocket.Debug;
import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.CloseFrame; 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.generator.Generator;
import org.eclipse.jetty.websocket.parser.FrameParseCapture; import org.eclipse.jetty.websocket.parser.FrameParseCapture;
import org.eclipse.jetty.websocket.parser.Parser; import org.eclipse.jetty.websocket.parser.Parser;
import org.eclipse.jetty.websocket.parser.PingPayloadParser;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -24,90 +20,21 @@ public class TestABCase7_3
{ {
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
@Test
public void testGenerateEmptyCloseCase7_3_1()
{
CloseFrame closeFrame = new CloseFrame();
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)0x00 });
actual.flip();
expected.flip();
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) @Test (expected = WebSocketException.class)
public void testGenerate1BytePayloadCloseCase7_3_2() public void testGenerate1BytePayloadCloseCase7_3_2()
{ {
CloseFrame pingFrame = new CloseFrame(); CloseFrame pingFrame = new CloseFrame();
pingFrame.setPayload(new byte[] {0x00}); pingFrame.setPayload(new byte[] {0x00});
Generator generator = new Generator(policy); Generator generator = new Generator(policy);
ByteBuffer actual = ByteBuffer.allocate(32); ByteBuffer actual = ByteBuffer.allocate(32);
generator.generate(actual, pingFrame); generator.generate(actual, pingFrame);
} }
@Test
public void testParse1BytePayloadCloseCase7_3_2()
{
Debug.enableDebugLogging(Parser.class);
ByteBuffer expected = ByteBuffer.allocate(32);
expected.put(new byte[]
{ (byte)0x88, 0x01, 0x00 });
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 @Test
public void testGenerateCloseWithStatusCase7_3_3() public void testGenerateCloseWithStatusCase7_3_3()
{ {
CloseFrame closeFrame = new CloseFrame(1000); CloseFrame closeFrame = new CloseFrame(1000);
Generator generator = new Generator(policy); Generator generator = new Generator(policy);
ByteBuffer actual = ByteBuffer.allocate(32); ByteBuffer actual = ByteBuffer.allocate(32);
@ -117,35 +44,290 @@ public class TestABCase7_3
expected.put(new byte[] expected.put(new byte[]
{ (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 }); { (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 });
actual.flip(); actual.flip();
expected.flip(); expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual); ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
} }
@Test @Test
public void testParseCloseWithStatusCase7_3_3() 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()
{
CloseFrame closeFrame = new CloseFrame();
Generator generator = new Generator(policy);
ByteBuffer actual = ByteBuffer.allocate(32);
generator.generate(actual, closeFrame);
ByteBuffer expected = ByteBuffer.allocate(5); ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[] expected.put(new byte[]
{ (byte)0x88, (byte)0x00 }); { (byte)0x88, (byte)0x00 });
actual.flip();
expected.flip(); expected.flip();
ByteBufferAssert.assertEquals("buffers do not match",expected,actual);
}
@Test
public void testParse1BytePayloadCloseCase7_3_2()
{
Debug.enableDebugLogging(Parser.class);
ByteBuffer expected = ByteBuffer.allocate(32);
expected.put(new byte[]
{ (byte)0x88, 0x01, 0x00 });
expected.flip();
Parser parser = new Parser(policy); Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture(); FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture); parser.addListener(capture);
parser.parse(expected); 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 testParseCloseWithStatusCase7_3_3()
{
ByteBuffer expected = ByteBuffer.allocate(5);
expected.put(new byte[]
{ (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 });
expected.flip();
Parser parser = new Parser(policy);
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(expected);
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(CloseFrame.class,1); 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 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);
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); CloseFrame pActual = (CloseFrame)capture.getFrames().get(0);
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0)); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0));
ByteBufferAssert.assertSize("CloseFrame.payload",0,pActual.getPayload()); ByteBufferAssert.assertSize("CloseFrame.payload",0,pActual.getPayload());
} }
} }