move a test around, add in the basics of a frame builder and some test cases using it as an example, need to decide to complete the builder with masking or smoke it
This commit is contained in:
parent
8fa35533b6
commit
23c6c81615
|
@ -14,7 +14,7 @@
|
|||
|
||||
<modules>
|
||||
<module>websocket-core</module>
|
||||
<!-- <module>websocket-client</module> -->
|
||||
<module>websocket-client</module>
|
||||
<module>websocket-server</module>
|
||||
</modules>
|
||||
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.websocket.api.PolicyViolationException;
|
||||
import org.eclipse.jetty.websocket.protocol.OpCode;
|
||||
|
||||
|
||||
public class FrameBuilder
|
||||
{
|
||||
public static FrameBuilder binaryFrame()
|
||||
{
|
||||
return new FrameBuilder(new BaseFrame(OpCode.BINARY));
|
||||
}
|
||||
|
||||
public static FrameBuilder closeFrame()
|
||||
{
|
||||
return new FrameBuilder(new BaseFrame(OpCode.CLOSE));
|
||||
}
|
||||
|
||||
public static FrameBuilder continuationFrame()
|
||||
{
|
||||
return new FrameBuilder(new BaseFrame(OpCode.CONTINUATION));
|
||||
}
|
||||
|
||||
public static FrameBuilder pingFrame()
|
||||
{
|
||||
return new FrameBuilder(new BaseFrame(OpCode.PING));
|
||||
}
|
||||
|
||||
public static FrameBuilder pongFrame()
|
||||
{
|
||||
return new FrameBuilder(new BaseFrame(OpCode.PONG));
|
||||
}
|
||||
|
||||
public static FrameBuilder textFrame()
|
||||
{
|
||||
return new FrameBuilder(new BaseFrame(OpCode.TEXT));
|
||||
}
|
||||
|
||||
private BaseFrame frame;
|
||||
|
||||
public FrameBuilder(BaseFrame frame)
|
||||
{
|
||||
this.frame = frame;
|
||||
this.frame.setFin(true); // default
|
||||
}
|
||||
|
||||
public byte[] asByteArray()
|
||||
{
|
||||
return BufferUtil.toArray(asByteBuffer());
|
||||
}
|
||||
|
||||
public ByteBuffer asByteBuffer()
|
||||
{
|
||||
ByteBuffer buffer = ByteBuffer.allocate(frame.getPayloadLength() + 32 );
|
||||
byte b;
|
||||
|
||||
// Setup fin thru opcode
|
||||
b = 0x00;
|
||||
if (frame.isFin())
|
||||
{
|
||||
b |= 0x80; // 1000_0000
|
||||
}
|
||||
if (frame.isRsv1())
|
||||
{
|
||||
b |= 0x40; // 0100_0000
|
||||
// TODO: extensions can negotiate this (somehow)
|
||||
throw new PolicyViolationException("RSV1 not allowed to be set");
|
||||
}
|
||||
if (frame.isRsv2())
|
||||
{
|
||||
b |= 0x20; // 0010_0000
|
||||
// TODO: extensions can negotiate this (somehow)
|
||||
throw new PolicyViolationException("RSV2 not allowed to be set");
|
||||
}
|
||||
if (frame.isRsv3())
|
||||
{
|
||||
b |= 0x10;
|
||||
// TODO: extensions can negotiate this (somehow)
|
||||
throw new PolicyViolationException("RSV3 not allowed to be set");
|
||||
}
|
||||
|
||||
byte opcode = frame.getOpCode().getCode();
|
||||
|
||||
if (frame.isContinuation())
|
||||
{
|
||||
// Continuations are not the same OPCODE
|
||||
opcode = OpCode.CONTINUATION.getCode();
|
||||
}
|
||||
|
||||
b |= opcode & 0x0F;
|
||||
|
||||
buffer.put(b);
|
||||
|
||||
// is masked
|
||||
b = 0x00;
|
||||
b |= (frame.isMasked()?0x80:0x00);
|
||||
|
||||
// payload lengths
|
||||
int payloadLength = frame.getPayloadLength();
|
||||
|
||||
/*
|
||||
* if length is over 65535 then its a 7 + 64 bit length
|
||||
*/
|
||||
if (payloadLength > 0xFF_FF)
|
||||
{
|
||||
// we have a 64 bit length
|
||||
b |= 0x7F;
|
||||
buffer.put(b); // indicate 8 byte length
|
||||
buffer.put((byte)0); //
|
||||
buffer.put((byte)0); // anything over an
|
||||
buffer.put((byte)0); // int is just
|
||||
buffer.put((byte)0); // intsane!
|
||||
buffer.put((byte)((payloadLength >> 24) & 0xFF));
|
||||
buffer.put((byte)((payloadLength >> 16) & 0xFF));
|
||||
buffer.put((byte)((payloadLength >> 8) & 0xFF));
|
||||
buffer.put((byte)(payloadLength & 0xFF));
|
||||
}
|
||||
/*
|
||||
* if payload is ge 126 we have a 7 + 16 bit length
|
||||
*/
|
||||
else if (payloadLength >= 0x7E)
|
||||
{
|
||||
b |= 0x7E;
|
||||
buffer.put(b); // indicate 2 byte length
|
||||
buffer.put((byte)(payloadLength >> 8));
|
||||
buffer.put((byte)(payloadLength & 0xFF));
|
||||
}
|
||||
/*
|
||||
* we have a 7 bit length
|
||||
*/
|
||||
else
|
||||
{
|
||||
b |= (payloadLength & 0x7F);
|
||||
buffer.put(b);
|
||||
}
|
||||
|
||||
// masking key
|
||||
if (frame.isMasked())
|
||||
{
|
||||
// TODO: figure out maskgen
|
||||
buffer.put(frame.getMask());
|
||||
}
|
||||
|
||||
// now the payload itself
|
||||
|
||||
// call back into masking check/method on this class?
|
||||
|
||||
// remember the position
|
||||
int positionPrePayload = buffer.position();
|
||||
|
||||
// generate payload
|
||||
if (frame.getPayloadLength() > 0)
|
||||
{
|
||||
BufferUtil.put(frame.getPayload(),buffer);
|
||||
}
|
||||
|
||||
int positionPostPayload = buffer.position();
|
||||
|
||||
// mask it if needed
|
||||
if (frame.isMasked())
|
||||
{
|
||||
// move back to remembered position.
|
||||
int size = positionPostPayload - positionPrePayload;
|
||||
byte[] mask = frame.getMask();
|
||||
int pos;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
pos = positionPrePayload + i;
|
||||
// Mask each byte by its absolute position in the bytebuffer
|
||||
buffer.put(pos,(byte)(buffer.get(pos) ^ mask[i % 4]));
|
||||
}
|
||||
}
|
||||
|
||||
BufferUtil.flipToFlush(buffer,0);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public BaseFrame asFrame()
|
||||
{
|
||||
return frame;
|
||||
}
|
||||
|
||||
public FrameBuilder isFin( boolean fin )
|
||||
{
|
||||
frame.setFin(fin);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FrameBuilder isRsv1(boolean rsv1)
|
||||
{
|
||||
frame.setRsv1(rsv1);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FrameBuilder isRsv2(boolean rsv2)
|
||||
{
|
||||
frame.setRsv2(rsv2);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FrameBuilder isRsv3(boolean rsv3)
|
||||
{
|
||||
frame.setRsv3(rsv3);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FrameBuilder withMask(byte[] mask)
|
||||
{
|
||||
frame.setMasked(true);
|
||||
frame.setMask(mask);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FrameBuilder withPayload(byte[] bytes)
|
||||
{
|
||||
frame.setPayload(bytes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FrameBuilder withPayload(ByteBuffer payload)
|
||||
{
|
||||
frame.setPayload(payload);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FrameBuilderTest
|
||||
{
|
||||
public void testSimpleAsFrame()
|
||||
{
|
||||
PingFrame frame = (PingFrame)FrameBuilder.pingFrame().asFrame();
|
||||
|
||||
Assert.assertTrue(frame instanceof PingFrame);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleInvalidCloseFrameBuilder()
|
||||
{
|
||||
byte[] actual = FrameBuilder.closeFrame().isFin(false).asByteArray();
|
||||
|
||||
byte[] expected = new byte[]
|
||||
{ (byte)0x08, (byte)0x00 };
|
||||
|
||||
Assert.assertArrayEquals(expected,actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleInvalidPingFrameBuilder()
|
||||
{
|
||||
byte[] actual = FrameBuilder.pingFrame().isFin(false).asByteArray();
|
||||
|
||||
byte[] expected = new byte[]
|
||||
{ (byte)0x09, (byte)0x00 };
|
||||
|
||||
Assert.assertArrayEquals(expected,actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleValidCloseFrame()
|
||||
{
|
||||
byte[] actual = FrameBuilder.closeFrame().asByteArray();
|
||||
|
||||
byte[] expected = new byte[]
|
||||
{ (byte)0x88, (byte)0x00 };
|
||||
|
||||
Assert.assertArrayEquals(expected,actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleValidPingFrame()
|
||||
{
|
||||
byte[] actual = FrameBuilder.pingFrame().asByteArray();
|
||||
|
||||
byte[] expected = new byte[]
|
||||
{ (byte)0x89, (byte)0x00 };
|
||||
|
||||
Assert.assertArrayEquals(expected,actual);
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* You may elect to redistribute this code under either of these licenses.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.jetty.websocket;
|
||||
package org.eclipse.jetty.websocket.generator;
|
||||
|
||||
/**
|
||||
*/
|
|
@ -13,13 +13,16 @@ import java.util.concurrent.TimeUnit;
|
|||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.ByteBufferAssert;
|
||||
import org.eclipse.jetty.websocket.protocol.OpCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
||||
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
||||
import org.eclipse.jetty.websocket.frames.CloseFrame;
|
||||
import org.eclipse.jetty.websocket.frames.FrameBuilder;
|
||||
import org.eclipse.jetty.websocket.frames.PingFrame;
|
||||
import org.eclipse.jetty.websocket.frames.PongFrame;
|
||||
import org.eclipse.jetty.websocket.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.generator.FrameGenerator;
|
||||
import org.eclipse.jetty.websocket.protocol.OpCode;
|
||||
import org.eclipse.jetty.websocket.server.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
||||
import org.eclipse.jetty.websocket.server.WebSocketServlet;
|
||||
|
@ -63,14 +66,14 @@ public class TestABCase5
|
|||
}
|
||||
|
||||
// echo the message back.
|
||||
try
|
||||
{
|
||||
getConnection().write(message);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
//try
|
||||
// {
|
||||
// getConnection().write(message);
|
||||
// }
|
||||
//catch (IOException e)
|
||||
// {
|
||||
// e.printStackTrace(System.err);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,10 +131,46 @@ public class TestABCase5
|
|||
|
||||
client.writeRaw(buf2);
|
||||
|
||||
// Read frame (hopefully text frame)
|
||||
// Read frame
|
||||
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||
CloseFrame closeFrame = (CloseFrame)frames.remove();
|
||||
Assert.assertThat("CloseFrame.status code",closeFrame.getStatusCode(),is(1002));
|
||||
BaseFrame frame = (BaseFrame)frames.remove();
|
||||
|
||||
Assert.assertTrue("frame should be close frame", frame instanceof CloseFrame);
|
||||
|
||||
Assert.assertThat("CloseFrame.status code",((CloseFrame)frame).getStatusCode(),is(1002));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase5_1PingIn2PacketsWithBuilder() throws Exception
|
||||
{
|
||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||
try
|
||||
{
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
String fragment1 = "fragment1";
|
||||
ByteBuffer frame1 = FrameBuilder.pingFrame().isFin(false).withPayload(fragment1.getBytes()).asByteBuffer();
|
||||
|
||||
client.writeRaw(frame1);
|
||||
|
||||
String fragment2 = "fragment2";
|
||||
ByteBuffer frame2 = FrameBuilder.pingFrame().withPayload(fragment2.getBytes()).asByteBuffer();
|
||||
client.writeRaw(frame2);
|
||||
|
||||
// Read frame
|
||||
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||
BaseFrame frame = (BaseFrame)frames.remove();
|
||||
|
||||
Assert.assertTrue("frame should be close frame", frame instanceof CloseFrame);
|
||||
|
||||
Assert.assertThat("CloseFrame.status code",((CloseFrame)frame).getStatusCode(),is(1002));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -178,10 +217,13 @@ public class TestABCase5
|
|||
|
||||
client.writeRaw(buf2);
|
||||
|
||||
// Read frame (hopefully text frame)
|
||||
// Read frame
|
||||
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||
CloseFrame closeFrame = (CloseFrame)frames.remove();
|
||||
Assert.assertThat("CloseFrame.status code",closeFrame.getStatusCode(),is(1002));
|
||||
BaseFrame frame = (BaseFrame)frames.remove();
|
||||
|
||||
Assert.assertTrue("frame should be close frame", frame instanceof CloseFrame);
|
||||
|
||||
Assert.assertThat("CloseFrame.status code",((CloseFrame)frame).getStatusCode(),is(1002));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -190,9 +232,45 @@ public class TestABCase5
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCase5_2PongIn2PacketsWithBuilder() throws Exception
|
||||
{
|
||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||
try
|
||||
{
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
String fragment1 = "fragment1";
|
||||
|
||||
ByteBuffer frame1 = FrameBuilder.pongFrame().isFin(false).withPayload(fragment1.getBytes()).asByteBuffer();
|
||||
|
||||
client.writeRaw(frame1);
|
||||
|
||||
String fragment2 = "fragment2";
|
||||
|
||||
ByteBuffer frame2 = FrameBuilder.continuationFrame().isFin(false).withPayload(fragment2.getBytes()).asByteBuffer();
|
||||
|
||||
client.writeRaw(frame2);
|
||||
|
||||
// Read frame
|
||||
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||
BaseFrame frame = (BaseFrame)frames.remove();
|
||||
|
||||
Assert.assertTrue("frame should be close frame", frame instanceof CloseFrame);
|
||||
|
||||
Assert.assertThat("CloseFrame.status code",((CloseFrame)frame).getStatusCode(),is(1002));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore ("not re-assembling the strings yet on server side echo")
|
||||
@Ignore ("not supported in implementation yet, requires server side message aggregation")
|
||||
public void testCase5_3TextIn2Packets() throws Exception
|
||||
{
|
||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||
|
@ -231,10 +309,204 @@ public class TestABCase5
|
|||
|
||||
client.writeRaw(buf2);
|
||||
|
||||
// Read frame (hopefully text frame)
|
||||
// Read frame
|
||||
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||
TextFrame textFrame = (TextFrame)frames.remove();
|
||||
Assert.assertThat("TextFrame.payload",textFrame.getPayloadUTF8(),is(fragment1 + fragment2));
|
||||
BaseFrame frame = (BaseFrame)frames.remove();
|
||||
|
||||
Assert.assertTrue("frame should be text frame", frame instanceof TextFrame);
|
||||
|
||||
Assert.assertThat("TextFrame.payload",((TextFrame)frame).getPayloadUTF8(),is(fragment1 + fragment2));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore ("not supported in implementation yet, requires server side message aggregation")
|
||||
public void testCase5_6TextPingRemainingText() throws Exception
|
||||
{
|
||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||
try
|
||||
{
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
// Send a text packet
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||
BufferUtil.clearToFill(buf);
|
||||
|
||||
String fragment1 = "fragment1";
|
||||
|
||||
buf.put((byte)(0x00 | OpCode.TEXT.getCode()));
|
||||
|
||||
byte b = 0x00; // no masking
|
||||
b |= fragment1.length() & 0x7F;
|
||||
buf.put(b);
|
||||
buf.put(fragment1.getBytes());
|
||||
BufferUtil.flipToFlush(buf,0);
|
||||
|
||||
client.writeRaw(buf);
|
||||
|
||||
// Send a ping with payload
|
||||
|
||||
ByteBuffer pingBuf = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||
BufferUtil.clearToFill(pingBuf);
|
||||
|
||||
String pingPayload = "ping payload";
|
||||
|
||||
pingBuf.put((byte)(0x00 | OpCode.PING.getCode()));
|
||||
|
||||
b = 0x00; // no masking
|
||||
b |= pingPayload.length() & 0x7F;
|
||||
pingBuf.put(b);
|
||||
pingBuf.put(pingPayload.getBytes());
|
||||
BufferUtil.flipToFlush(pingBuf,0);
|
||||
|
||||
client.writeRaw(buf);
|
||||
|
||||
// Send remaining text as continuation
|
||||
|
||||
ByteBuffer buf2 = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||
BufferUtil.clearToFill(buf2);
|
||||
|
||||
String fragment2 = "fragment2";
|
||||
|
||||
buf2.put((byte)(0x80 | OpCode.CONTINUATION.getCode()));
|
||||
b = 0x00; // no masking
|
||||
b |= fragment2.length() & 0x7F;
|
||||
buf2.put(b);
|
||||
buf2.put(fragment2.getBytes());
|
||||
BufferUtil.flipToFlush(buf2,0);
|
||||
|
||||
client.writeRaw(buf2);
|
||||
|
||||
// Should be 2 frames, pong frame followed by combined echo'd text frame
|
||||
Queue<BaseFrame> frames = client.readFrames(2,TimeUnit.MILLISECONDS,500);
|
||||
BaseFrame frame = frames.remove();
|
||||
|
||||
Assert.assertTrue("first frame should be pong frame", frame instanceof PongFrame );
|
||||
|
||||
ByteBuffer payload1 = ByteBuffer.allocate(pingPayload.length());
|
||||
payload1.flip();
|
||||
|
||||
ByteBufferAssert.assertEquals("payloads should be equal" , payload1, ((PongFrame)frame).getPayload() );
|
||||
|
||||
frame = (BaseFrame)frames.remove();
|
||||
|
||||
Assert.assertTrue("second frame should be text frame", frame instanceof TextFrame );
|
||||
|
||||
|
||||
Assert.assertThat("TextFrame.payload",((TextFrame)frame).getPayloadUTF8(),is(fragment1 + fragment2));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore ("not supported in implementation yet, requires server side message aggregation")
|
||||
public void testCase5_6TextPingRemainingTextWithBuilder() throws Exception
|
||||
{
|
||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||
try
|
||||
{
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
// Send a text packet
|
||||
String textPayload1 = "fragment1";
|
||||
|
||||
ByteBuffer frame1 = FrameBuilder.textFrame().isFin(false).withPayload(textPayload1.getBytes()).asByteBuffer();
|
||||
BufferUtil.flipToFlush(frame1,0);
|
||||
client.writeRaw(frame1);
|
||||
|
||||
// Send a ping with payload
|
||||
|
||||
String pingPayload = "ping payload";
|
||||
ByteBuffer frame2 = FrameBuilder.pingFrame().withPayload(pingPayload.getBytes()).asByteBuffer();
|
||||
BufferUtil.flipToFlush(frame2,0);
|
||||
|
||||
client.writeRaw(frame2);
|
||||
|
||||
// Send remaining text as continuation
|
||||
String textPayload2 = "fragment2";
|
||||
|
||||
ByteBuffer frame3 = FrameBuilder.continuationFrame().withPayload(textPayload2.getBytes()).asByteBuffer();
|
||||
BufferUtil.flipToFlush(frame3,0);
|
||||
|
||||
client.writeRaw(frame3);
|
||||
|
||||
// Should be 2 frames, pong frame followed by combined echo'd text frame
|
||||
Queue<BaseFrame> frames = client.readFrames(2,TimeUnit.MILLISECONDS,500);
|
||||
BaseFrame frame = frames.remove();
|
||||
|
||||
Assert.assertTrue("first frame should be pong frame", frame instanceof PongFrame );
|
||||
|
||||
ByteBuffer payload1 = ByteBuffer.allocate(pingPayload.length());
|
||||
payload1.flip();
|
||||
|
||||
ByteBufferAssert.assertEquals("payloads should be equal" , payload1, ((PongFrame)frame).getPayload() );
|
||||
|
||||
frame = (BaseFrame)frames.remove();
|
||||
|
||||
Assert.assertTrue("second frame should be text frame", frame instanceof TextFrame );
|
||||
|
||||
|
||||
Assert.assertThat("TextFrame.payload",((TextFrame)frame).getPayloadUTF8(),is(textPayload1 + textPayload2));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore ("AB tests have chop concepts currently unsupported by test...I think, also the string being returns is not Bad Continuation")
|
||||
public void testCase5_9BadContinuation() throws Exception
|
||||
{
|
||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||
try
|
||||
{
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
// Send a text packet
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||
BufferUtil.clearToFill(buf);
|
||||
|
||||
String fragment1 = "fragment";
|
||||
|
||||
// continutation w / FIN
|
||||
|
||||
buf.put((byte)(0x80 | OpCode.CONTINUATION.getCode()));
|
||||
|
||||
byte b = 0x00; // no masking
|
||||
b |= fragment1.length() & 0x7F;
|
||||
buf.put(b);
|
||||
buf.put(fragment1.getBytes());
|
||||
BufferUtil.flipToFlush(buf,0);
|
||||
|
||||
client.writeRaw(buf);
|
||||
|
||||
// Read frame
|
||||
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||
BaseFrame frame = (BaseFrame)frames.remove();
|
||||
|
||||
Assert.assertTrue("frame should be close frame", frame instanceof CloseFrame);
|
||||
|
||||
Assert.assertThat("CloseFrame.status code",((CloseFrame)frame).getStatusCode(),is(1002));
|
||||
|
||||
Assert.assertThat("CloseFrame.reason", ((CloseFrame)frame).getReason(),is("Bad Continuation") ); // TODO put close reasons into public strings in impl someplace
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
||||
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
||||
import org.eclipse.jetty.websocket.frames.CloseFrame;
|
||||
import org.eclipse.jetty.websocket.frames.FrameBuilder;
|
||||
import org.eclipse.jetty.websocket.generator.FrameGenerator;
|
||||
import org.eclipse.jetty.websocket.protocol.OpCode;
|
||||
import org.eclipse.jetty.websocket.server.SimpleServletServer;
|
||||
|
@ -168,4 +169,46 @@ public class TestABCase7_9
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the requirement of issuing
|
||||
*/
|
||||
@Test
|
||||
public void testCase7_9_XInvalidCloseStatusCodesWithBuilder() throws Exception
|
||||
{
|
||||
BlockheadClient client = new BlockheadClient(server.getServerUri());
|
||||
try
|
||||
{
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
ByteBuffer frame = FrameBuilder.closeFrame().withMask(new byte[]
|
||||
{ 0x44, 0x44, 0x44, 0x44 }).asByteBuffer();
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(FrameGenerator.OVERHEAD + 2);
|
||||
BufferUtil.clearToFill(buf);
|
||||
|
||||
// Create Close Frame manually, as we are testing the server's behavior of a bad client.
|
||||
buf.put((byte)(0x80 | OpCode.CLOSE.getCode()));
|
||||
buf.put((byte)(0x80 | 2));
|
||||
byte mask[] = new byte[]
|
||||
{ 0x44, 0x44, 0x44, 0x44 };
|
||||
buf.put(mask);
|
||||
int position = buf.position();
|
||||
buf.putChar((char)this.invalidStatusCode);
|
||||
remask(buf,position,mask);
|
||||
BufferUtil.flipToFlush(buf,0);
|
||||
client.writeRaw(buf);
|
||||
|
||||
// Read frame (hopefully text frame)
|
||||
Queue<BaseFrame> frames = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||
CloseFrame closeFrame = (CloseFrame)frames.remove();
|
||||
Assert.assertThat("CloseFrame.status code",closeFrame.getStatusCode(),is(1002));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue