Making WebSocketFrame use builder pattern

This commit is contained in:
Joakim Erdfelt 2012-07-10 11:12:10 -07:00
parent 20876011e0
commit c2f1d23f2b
6 changed files with 191 additions and 32 deletions

View File

@ -199,4 +199,5 @@ public class WebSocketPolicy
{
this.maxTextMessageSize = maxTextMessageSize;
}
}

View File

@ -46,26 +46,57 @@ public class Generator
public static final int OVERHEAD = 28;
private final WebSocketPolicy policy;
private static ByteBufferPool bufferPool;
private final ByteBufferPool bufferPool;
private boolean validating;
/**
*
* @param policy
* @deprecated discouraged usage form
*/
@Deprecated
public Generator(WebSocketPolicy policy)
{
this.policy = policy;
if (this.bufferPool == null)
{
this.bufferPool = new StandardByteBufferPool();
}
this(policy,new StandardByteBufferPool());
}
/**
* Construct Generator with provided policy and bufferPool
*
* @param policy
* the policy to use
* @param bufferPool
* the buffer pool to use
*/
public Generator(WebSocketPolicy policy, ByteBufferPool bufferPool)
{
this(policy,bufferPool,true);
}
/**
* Construct Generator with provided policy and bufferPool
*
* @param policy
* the policy to use
* @param bufferPool
* the buffer pool to use
* @param validating
* true to enable RFC frame validation
*/
public Generator(WebSocketPolicy policy, ByteBufferPool bufferPool, boolean validating)
{
this.policy = policy;
this.bufferPool = bufferPool;
this.validating = validating;
}
public void assertFrameValid(WebSocketFrame frame)
{
if (!validating)
{
return;
}
/*
* RFC 6455 Section 5.2
*
@ -262,11 +293,6 @@ public class Generator
return generate(bufferSize,frame);
}
public void init(ByteBufferPool pool)
{
}
@Override
public String toString()
{

View File

@ -3,6 +3,7 @@ package org.eclipse.jetty.websocket.protocol;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.ProtocolException;
@ -66,11 +67,42 @@ public class CloseInfo
}
}
public CloseInfo(int statusCode, String reason)
{
this.statusCode = statusCode;
this.reason = reason;
}
public CloseInfo(WebSocketFrame frame)
{
this(frame.getPayload(),false);
}
public ByteBuffer asByteBuffer()
{
if (statusCode != (-1))
{
ByteBuffer buf = ByteBuffer.allocate(WebSocketFrame.MAX_CONTROL_PAYLOAD);
buf.putChar((char)statusCode);
if (StringUtil.isNotBlank(reason))
{
byte utf[] = StringUtil.getUtf8Bytes(reason);
buf.put(utf,0,utf.length);
}
BufferUtil.flipToFlush(buf,0);
return buf;
}
return null;
}
public WebSocketFrame asFrame()
{
WebSocketFrame frame = new WebSocketFrame(OpCode.CLOSE);
frame.setFin(true);
frame.setPayload(asByteBuffer());
return frame;
}
public String getReason()
{
return reason;

View File

@ -18,9 +18,11 @@ import org.eclipse.jetty.websocket.generator.Generator;
*/
public class FrameBuilder
{
/**
* A Generator that doesn't
*/
public class DirtyGenerator extends Generator
{
public DirtyGenerator()
{
super(WebSocketPolicy.newServerPolicy(),bufferPool);
@ -30,10 +32,9 @@ public class FrameBuilder
public void assertFrameValid(WebSocketFrame frame)
{
/*
* we desire the ability to craft bad frames so ignore frame validation
* Do no validation of the frame validity. <p> we desire the ability to craft bad frames so we'll ignore frame validation
*/
}
}
private static ByteBufferPool bufferPool = new StandardByteBufferPool();

View File

@ -34,7 +34,7 @@ public class WebSocketFrame implements Frame
/** Maximum size of Control frame, per RFC 6455 */
public static final int MAX_CONTROL_PAYLOAD = 125;
private boolean fin = false;
private boolean fin = true;
private boolean rsv1 = false;
private boolean rsv2 = false;
private boolean rsv3 = false;
@ -215,7 +215,7 @@ public class WebSocketFrame implements Frame
public void reset()
{
fin = false;
fin = true;
rsv1 = false;
rsv2 = false;
rsv3 = false;
@ -227,35 +227,41 @@ public class WebSocketFrame implements Frame
continuation = false;
}
public void setContinuation(boolean continuation)
public WebSocketFrame setContinuation(boolean continuation)
{
this.continuation = continuation;
return this;
}
public void setContinuationIndex(int continuationIndex)
public WebSocketFrame setContinuationIndex(int continuationIndex)
{
this.continuationIndex = continuationIndex;
return this;
}
public void setFin(boolean fin)
public WebSocketFrame setFin(boolean fin)
{
this.fin = fin;
return this;
}
public void setMask(byte[] maskingKey)
public WebSocketFrame setMask(byte[] maskingKey)
{
this.mask = maskingKey;
this.masked = (mask != null);
return this;
}
public void setMasked(boolean mask)
public WebSocketFrame setMasked(boolean mask)
{
this.masked = mask;
return this;
}
public void setOpCode(OpCode opCode)
public WebSocketFrame setOpCode(OpCode opCode)
{
this.opcode = opCode;
return this;
}
/**
@ -264,12 +270,12 @@ public class WebSocketFrame implements Frame
* @param buf
* the bytebuffer to set
*/
public void setPayload(byte buf[])
public WebSocketFrame setPayload(byte buf[])
{
if (buf == null)
{
data = null;
return;
return this;
}
if (opcode.isControlFrame())
@ -284,6 +290,7 @@ public class WebSocketFrame implements Frame
data = ByteBuffer.allocate(len);
BufferUtil.clearToFill(data);
data.put(buf,0,len);
return this;
}
/**
@ -292,12 +299,12 @@ public class WebSocketFrame implements Frame
* @param buf
* the bytebuffer to set
*/
public void setPayload(byte buf[], int offset, int len)
public WebSocketFrame setPayload(byte buf[], int offset, int len)
{
if (buf == null)
{
data = null;
return;
return this;
}
if (opcode.isControlFrame())
@ -311,6 +318,7 @@ public class WebSocketFrame implements Frame
data = ByteBuffer.allocate(len);
BufferUtil.clearToFill(data);
data.put(buf,0,len);
return this;
}
/**
@ -323,12 +331,12 @@ public class WebSocketFrame implements Frame
* @param buf
* the bytebuffer to set
*/
public void setPayload(ByteBuffer buf)
public WebSocketFrame setPayload(ByteBuffer buf)
{
if (buf == null)
{
data = null;
return;
return this;
}
if (opcode.isControlFrame())
@ -340,21 +348,25 @@ public class WebSocketFrame implements Frame
}
data = buf.slice();
return this;
}
public void setRsv1(boolean rsv1)
public WebSocketFrame setRsv1(boolean rsv1)
{
this.rsv1 = rsv1;
return this;
}
public void setRsv2(boolean rsv2)
public WebSocketFrame setRsv2(boolean rsv2)
{
this.rsv2 = rsv2;
return this;
}
public void setRsv3(boolean rsv3)
public WebSocketFrame setRsv3(boolean rsv3)
{
this.rsv3 = rsv3;
return this;
}
@Override

View File

@ -0,0 +1,87 @@
package org.eclipse.jetty.websocket.protocol;
import java.nio.ByteBuffer;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.StandardByteBufferPool;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.ByteBufferAssert;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.generator.Generator;
import org.junit.BeforeClass;
import org.junit.Test;
public class WebSocketFrameTest
{
private static Generator strictGenerator;
private static Generator laxGenerator;
@BeforeClass
public static void initGenerator()
{
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
ByteBufferPool bufferPool = new StandardByteBufferPool();
strictGenerator = new Generator(policy,bufferPool);
laxGenerator = new Generator(policy,bufferPool,false);
}
private void assertEqual(String message, ByteBuffer expected, ByteBuffer actual)
{
BufferUtil.flipToFlush(actual,0);
BufferUtil.flipToFlush(expected,0);
ByteBufferAssert.assertEquals(message,expected,actual);
}
@Test
public void testLaxInvalidClose()
{
WebSocketFrame frame = new WebSocketFrame(OpCode.CLOSE).setFin(false);
ByteBuffer actual = laxGenerator.generate(frame);
ByteBuffer expected = ByteBuffer.allocate(2);
expected.put((byte)0x08);
expected.put((byte)0x00);
assertEqual("Lax Invalid Close Frame",expected,actual);
}
@Test
public void testLaxInvalidPing()
{
WebSocketFrame frame = new WebSocketFrame(OpCode.PING).setFin(false);
ByteBuffer actual = laxGenerator.generate(frame);
ByteBuffer expected = ByteBuffer.allocate(2);
expected.put((byte)0x09);
expected.put((byte)0x00);
assertEqual("Lax Invalid Ping Frame",expected,actual);
}
@Test
public void testStrictValidClose()
{
CloseInfo close = new CloseInfo(StatusCode.NORMAL,null);
ByteBuffer actual = strictGenerator.generate(close.asFrame());
ByteBuffer expected = ByteBuffer.allocate(4);
expected.put((byte)0x88);
expected.put((byte)0x02);
expected.put((byte)0x03);
expected.put((byte)0xE8);
assertEqual("Strict Valid Close Frame",expected,actual);
}
@Test
public void testStrictValidPing()
{
WebSocketFrame frame = new WebSocketFrame(OpCode.PING);
ByteBuffer actual = strictGenerator.generate(frame);
ByteBuffer expected = ByteBuffer.allocate(2);
expected.put((byte)0x89);
expected.put((byte)0x00);
assertEqual("Strict Valid Ping Frame",expected,actual);
}
}