Making WebSocketFrame use builder pattern
This commit is contained in:
parent
20876011e0
commit
c2f1d23f2b
|
@ -199,4 +199,5 @@ public class WebSocketPolicy
|
||||||
{
|
{
|
||||||
this.maxTextMessageSize = maxTextMessageSize;
|
this.maxTextMessageSize = maxTextMessageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,26 +46,57 @@ public class Generator
|
||||||
public static final int OVERHEAD = 28;
|
public static final int OVERHEAD = 28;
|
||||||
|
|
||||||
private final WebSocketPolicy policy;
|
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)
|
public Generator(WebSocketPolicy policy)
|
||||||
{
|
{
|
||||||
this.policy = policy;
|
this(policy,new StandardByteBufferPool());
|
||||||
|
|
||||||
if (this.bufferPool == null)
|
|
||||||
{
|
|
||||||
this.bufferPool = 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)
|
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.policy = policy;
|
||||||
this.bufferPool = bufferPool;
|
this.bufferPool = bufferPool;
|
||||||
|
this.validating = validating;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertFrameValid(WebSocketFrame frame)
|
public void assertFrameValid(WebSocketFrame frame)
|
||||||
{
|
{
|
||||||
|
if (!validating)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RFC 6455 Section 5.2
|
* RFC 6455 Section 5.2
|
||||||
*
|
*
|
||||||
|
@ -262,11 +293,6 @@ public class Generator
|
||||||
return generate(bufferSize,frame);
|
return generate(bufferSize,frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(ByteBufferPool pool)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.eclipse.jetty.websocket.protocol;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
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.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.websocket.api.ProtocolException;
|
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)
|
public CloseInfo(WebSocketFrame frame)
|
||||||
{
|
{
|
||||||
this(frame.getPayload(),false);
|
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()
|
public String getReason()
|
||||||
{
|
{
|
||||||
return reason;
|
return reason;
|
||||||
|
|
|
@ -18,9 +18,11 @@ import org.eclipse.jetty.websocket.generator.Generator;
|
||||||
*/
|
*/
|
||||||
public class FrameBuilder
|
public class FrameBuilder
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* A Generator that doesn't
|
||||||
|
*/
|
||||||
public class DirtyGenerator extends Generator
|
public class DirtyGenerator extends Generator
|
||||||
{
|
{
|
||||||
|
|
||||||
public DirtyGenerator()
|
public DirtyGenerator()
|
||||||
{
|
{
|
||||||
super(WebSocketPolicy.newServerPolicy(),bufferPool);
|
super(WebSocketPolicy.newServerPolicy(),bufferPool);
|
||||||
|
@ -30,10 +32,9 @@ public class FrameBuilder
|
||||||
public void assertFrameValid(WebSocketFrame frame)
|
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();
|
private static ByteBufferPool bufferPool = new StandardByteBufferPool();
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class WebSocketFrame implements Frame
|
||||||
/** Maximum size of Control frame, per RFC 6455 */
|
/** Maximum size of Control frame, per RFC 6455 */
|
||||||
public static final int MAX_CONTROL_PAYLOAD = 125;
|
public static final int MAX_CONTROL_PAYLOAD = 125;
|
||||||
|
|
||||||
private boolean fin = false;
|
private boolean fin = true;
|
||||||
private boolean rsv1 = false;
|
private boolean rsv1 = false;
|
||||||
private boolean rsv2 = false;
|
private boolean rsv2 = false;
|
||||||
private boolean rsv3 = false;
|
private boolean rsv3 = false;
|
||||||
|
@ -215,7 +215,7 @@ public class WebSocketFrame implements Frame
|
||||||
|
|
||||||
public void reset()
|
public void reset()
|
||||||
{
|
{
|
||||||
fin = false;
|
fin = true;
|
||||||
rsv1 = false;
|
rsv1 = false;
|
||||||
rsv2 = false;
|
rsv2 = false;
|
||||||
rsv3 = false;
|
rsv3 = false;
|
||||||
|
@ -227,35 +227,41 @@ public class WebSocketFrame implements Frame
|
||||||
continuation = false;
|
continuation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContinuation(boolean continuation)
|
public WebSocketFrame setContinuation(boolean continuation)
|
||||||
{
|
{
|
||||||
this.continuation = continuation;
|
this.continuation = continuation;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContinuationIndex(int continuationIndex)
|
public WebSocketFrame setContinuationIndex(int continuationIndex)
|
||||||
{
|
{
|
||||||
this.continuationIndex = continuationIndex;
|
this.continuationIndex = continuationIndex;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFin(boolean fin)
|
public WebSocketFrame setFin(boolean fin)
|
||||||
{
|
{
|
||||||
this.fin = fin;
|
this.fin = fin;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMask(byte[] maskingKey)
|
public WebSocketFrame setMask(byte[] maskingKey)
|
||||||
{
|
{
|
||||||
this.mask = maskingKey;
|
this.mask = maskingKey;
|
||||||
this.masked = (mask != null);
|
this.masked = (mask != null);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMasked(boolean mask)
|
public WebSocketFrame setMasked(boolean mask)
|
||||||
{
|
{
|
||||||
this.masked = mask;
|
this.masked = mask;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOpCode(OpCode opCode)
|
public WebSocketFrame setOpCode(OpCode opCode)
|
||||||
{
|
{
|
||||||
this.opcode = opCode;
|
this.opcode = opCode;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -264,12 +270,12 @@ public class WebSocketFrame implements Frame
|
||||||
* @param buf
|
* @param buf
|
||||||
* the bytebuffer to set
|
* the bytebuffer to set
|
||||||
*/
|
*/
|
||||||
public void setPayload(byte buf[])
|
public WebSocketFrame setPayload(byte buf[])
|
||||||
{
|
{
|
||||||
if (buf == null)
|
if (buf == null)
|
||||||
{
|
{
|
||||||
data = null;
|
data = null;
|
||||||
return;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode.isControlFrame())
|
if (opcode.isControlFrame())
|
||||||
|
@ -284,6 +290,7 @@ public class WebSocketFrame implements Frame
|
||||||
data = ByteBuffer.allocate(len);
|
data = ByteBuffer.allocate(len);
|
||||||
BufferUtil.clearToFill(data);
|
BufferUtil.clearToFill(data);
|
||||||
data.put(buf,0,len);
|
data.put(buf,0,len);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -292,12 +299,12 @@ public class WebSocketFrame implements Frame
|
||||||
* @param buf
|
* @param buf
|
||||||
* the bytebuffer to set
|
* 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)
|
if (buf == null)
|
||||||
{
|
{
|
||||||
data = null;
|
data = null;
|
||||||
return;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode.isControlFrame())
|
if (opcode.isControlFrame())
|
||||||
|
@ -311,6 +318,7 @@ public class WebSocketFrame implements Frame
|
||||||
data = ByteBuffer.allocate(len);
|
data = ByteBuffer.allocate(len);
|
||||||
BufferUtil.clearToFill(data);
|
BufferUtil.clearToFill(data);
|
||||||
data.put(buf,0,len);
|
data.put(buf,0,len);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -323,12 +331,12 @@ public class WebSocketFrame implements Frame
|
||||||
* @param buf
|
* @param buf
|
||||||
* the bytebuffer to set
|
* the bytebuffer to set
|
||||||
*/
|
*/
|
||||||
public void setPayload(ByteBuffer buf)
|
public WebSocketFrame setPayload(ByteBuffer buf)
|
||||||
{
|
{
|
||||||
if (buf == null)
|
if (buf == null)
|
||||||
{
|
{
|
||||||
data = null;
|
data = null;
|
||||||
return;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode.isControlFrame())
|
if (opcode.isControlFrame())
|
||||||
|
@ -340,21 +348,25 @@ public class WebSocketFrame implements Frame
|
||||||
}
|
}
|
||||||
|
|
||||||
data = buf.slice();
|
data = buf.slice();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRsv1(boolean rsv1)
|
public WebSocketFrame setRsv1(boolean rsv1)
|
||||||
{
|
{
|
||||||
this.rsv1 = rsv1;
|
this.rsv1 = rsv1;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRsv2(boolean rsv2)
|
public WebSocketFrame setRsv2(boolean rsv2)
|
||||||
{
|
{
|
||||||
this.rsv2 = rsv2;
|
this.rsv2 = rsv2;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRsv3(boolean rsv3)
|
public WebSocketFrame setRsv3(boolean rsv3)
|
||||||
{
|
{
|
||||||
this.rsv3 = rsv3;
|
this.rsv3 = rsv3;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue