Next step in simplifying the frames

This commit is contained in:
Joakim Erdfelt 2012-07-06 11:32:22 -07:00
parent b515e845cc
commit dfc9315bc7
35 changed files with 385 additions and 1123 deletions

View File

@ -89,6 +89,15 @@ public class WebSocketPolicy
}
}
public void assertValidPayloadLength(int payloadLength)
{
// validate to buffer sizes
if (payloadLength > bufferSize)
{
throw new PolicyViolationException("Requested payload length [" + payloadLength + "] exceeds maximum size [" + bufferSize + "]");
}
}
public void assertValidTextMessageSize(int requestedSize)
{
if (maxTextMessageSize > 0)

View File

@ -9,9 +9,9 @@ import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.frames.FrameBuilder;
import org.eclipse.jetty.websocket.generator.Generator;
import org.eclipse.jetty.websocket.io.RawConnection;
import org.eclipse.jetty.websocket.protocol.FrameBuilder;
/**
* For working with the {@link WebSocketConnection} in a blocking technique.

View File

@ -8,9 +8,10 @@ import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.PingFrame;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.generator.Generator;
import org.eclipse.jetty.websocket.io.RawConnection;
import org.eclipse.jetty.websocket.protocol.FrameBuilder;
public class WebSocketPing
{
@ -36,7 +37,7 @@ public class WebSocketPing
public void sendPing(byte data[]) throws IOException
{
PingFrame frame = new PingFrame(data);
BaseFrame frame = FrameBuilder.ping().payload(data).asFrame();
ByteBuffer buf = bufferPool.acquire(policy.getBufferSize(),false);
try
{

View File

@ -16,14 +16,12 @@ import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketListener;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.frames.CloseFrame;
import org.eclipse.jetty.websocket.frames.DataFrame;
import org.eclipse.jetty.websocket.frames.DataFrame.BinaryFrame;
import org.eclipse.jetty.websocket.io.MessageInputStream;
import org.eclipse.jetty.websocket.io.MessageReader;
import org.eclipse.jetty.websocket.io.StreamAppender;
import org.eclipse.jetty.websocket.parser.Parser;
import org.eclipse.jetty.websocket.protocol.Frame;
import org.eclipse.jetty.websocket.util.CloseUtil;
/**
* Responsible for routing the internally generated events destined for a specific WebSocket instance to whatever choice of development style the developer has
@ -124,157 +122,148 @@ public class WebSocketEventDriver implements Parser.Listener
// DO NOT return; - as this is just a read-only notification.
}
// Specified Close Case
if ((frame instanceof CloseFrame) && (events.onClose != null))
{
CloseFrame close = (CloseFrame)frame;
events.onClose.call(websocket,connection,close.getStatusCode(),close.getReason());
return;
}
try
{
// Work a Data Frame
if (frame instanceof DataFrame)
switch (frame.getOpCode())
{
DataFrame data = (DataFrame)frame;
if ((events.onText == null) && (events.onBinary == null))
case CLOSE:
{
// skip
if (events.onClose != null)
{
byte payload[] = frame.getPayloadData();
int statusCode = CloseUtil.getStatusCode(payload);
String reason = CloseUtil.getReason(payload);
events.onClose.call(websocket,connection,statusCode,reason);
}
return;
}
switch (data.getOpCode())
case BINARY:
{
case BINARY:
if (events.onBinary.isStreaming())
{
if (events.onBinary.isStreaming())
boolean needsNotification = false;
// Streaming Approach
if (activeStream == null)
{
boolean needsNotification = false;
// Streaming Approach
if (activeStream == null)
{
// Allocate directly, not via ByteBufferPool, as this buffer
// is ultimately controlled by the end user, and we can't know
// when they are done using the stream in order to release any
// buffer allocated from the ByteBufferPool.
ByteBuffer buf = ByteBuffer.allocate(policy.getBufferSize());
this.activeStream = new MessageInputStream(buf);
needsNotification = true;
}
activeStream.appendBuffer(data.getPayload());
if (needsNotification)
{
events.onBinary.call(websocket,connection,activeStream);
}
if (data.isFin())
{
// close the stream.
activeStream.bufferComplete();
activeStream = null; // work with a new one
}
// Allocate directly, not via ByteBufferPool, as this buffer
// is ultimately controlled by the end user, and we can't know
// when they are done using the stream in order to release any
// buffer allocated from the ByteBufferPool.
ByteBuffer buf = ByteBuffer.allocate(policy.getBufferSize());
this.activeStream = new MessageInputStream(buf);
needsNotification = true;
}
else
activeStream.appendBuffer(frame.getPayload());
if (needsNotification)
{
if (activeMessage == null)
{
// Acquire from ByteBufferPool is safe here, as the return
// from the notification is a good place to release the
// buffer.
activeMessage = bufferPool.acquire(policy.getBufferSize(),false);
BufferUtil.clearToFill(activeMessage);
}
appendBuffer(activeMessage,data.getPayload());
// normal case
if (frame.isFin())
{
// Notify using simple message approach.
try
{
BufferUtil.flipToFlush(activeMessage,0);
byte buf[] = BufferUtil.toArray(activeMessage);
events.onBinary.call(websocket,connection,buf,0,buf.length);
}
finally
{
bufferPool.release(activeMessage);
activeMessage = null;
}
}
events.onBinary.call(websocket,connection,activeStream);
}
if (frame.isFin())
{
// close the stream.
activeStream.bufferComplete();
activeStream = null; // work with a new one
}
return;
}
case TEXT:
else
{
if (events.onText.isStreaming())
if (activeMessage == null)
{
boolean needsNotification = false;
// Acquire from ByteBufferPool is safe here, as the return
// from the notification is a good place to release the
// buffer.
activeMessage = bufferPool.acquire(policy.getBufferSize(),false);
BufferUtil.clearToFill(activeMessage);
}
// Streaming Approach
if (activeStream == null)
appendBuffer(activeMessage,frame.getPayload());
// normal case
if (frame.isFin())
{
// Notify using simple message approach.
try
{
// Allocate directly, not via ByteBufferPool, as this buffer
// is ultimately controlled by the end user, and we can't know
// when they are done using the stream in order to release any
// buffer allocated from the ByteBufferPool.
ByteBuffer buf = ByteBuffer.allocate(policy.getBufferSize());
this.activeStream = new MessageReader(buf);
needsNotification = true;
BufferUtil.flipToFlush(activeMessage,0);
byte buf[] = BufferUtil.toArray(activeMessage);
events.onBinary.call(websocket,connection,buf,0,buf.length);
}
activeStream.appendBuffer(data.getPayload());
if (needsNotification)
finally
{
events.onText.call(websocket,connection,activeStream);
}
if (data.isFin())
{
// close the stream.
activeStream.bufferComplete();
activeStream = null; // work with a new one
bufferPool.release(activeMessage);
activeMessage = null;
}
}
else
{
if (activeMessage == null)
{
// Acquire from ByteBufferPool is safe here, as the return
// from the notification is a good place to release the
// buffer.
activeMessage = bufferPool.acquire(policy.getBufferSize(),false);
BufferUtil.clearToFill(activeMessage);
}
appendBuffer(activeMessage,data.getPayload());
// normal case
if (frame.isFin())
{
// Notify using simple message approach.
try
{
BufferUtil.flipToFlush(activeMessage,0);
events.onText.call(websocket,connection,BufferUtil.toUTF8String(activeMessage));
}
finally
{
bufferPool.release(activeMessage);
activeMessage = null;
}
}
}
return;
}
return;
}
case TEXT:
{
if (events.onText.isStreaming())
{
boolean needsNotification = false;
// Streaming Approach
if (activeStream == null)
{
// Allocate directly, not via ByteBufferPool, as this buffer
// is ultimately controlled by the end user, and we can't know
// when they are done using the stream in order to release any
// buffer allocated from the ByteBufferPool.
ByteBuffer buf = ByteBuffer.allocate(policy.getBufferSize());
this.activeStream = new MessageReader(buf);
needsNotification = true;
}
activeStream.appendBuffer(frame.getPayload());
if (needsNotification)
{
events.onText.call(websocket,connection,activeStream);
}
if (frame.isFin())
{
// close the stream.
activeStream.bufferComplete();
activeStream = null; // work with a new one
}
}
else
{
if (activeMessage == null)
{
// Acquire from ByteBufferPool is safe here, as the return
// from the notification is a good place to release the
// buffer.
activeMessage = bufferPool.acquire(policy.getBufferSize(),false);
BufferUtil.clearToFill(activeMessage);
}
appendBuffer(activeMessage,frame.getPayload());
// normal case
if (frame.isFin())
{
// Notify using simple message approach.
try
{
BufferUtil.flipToFlush(activeMessage,0);
events.onText.call(websocket,connection,BufferUtil.toUTF8String(activeMessage));
}
finally
{
bufferPool.release(activeMessage);
activeMessage = null;
}
}
}
return;
}
}
}
@ -323,9 +312,9 @@ public class WebSocketEventDriver implements Parser.Listener
if (StringUtil.isNotBlank(reason))
{
// Trim big exception messages here.
if (reason.length() > CloseFrame.MAX_REASON)
if (reason.length() > (BaseFrame.MAX_CONTROL_PAYLOAD - 2))
{
reason = reason.substring(0,CloseFrame.MAX_REASON);
reason = reason.substring(0,BaseFrame.MAX_CONTROL_PAYLOAD - 2);
}
}
LOG.debug("terminateConnection({},{})",statusCode,rawreason);

View File

@ -2,6 +2,8 @@ package org.eclipse.jetty.websocket.frames;
import java.nio.ByteBuffer;
import javax.xml.ws.ProtocolException;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.protocol.Frame;
import org.eclipse.jetty.websocket.protocol.OpCode;
@ -32,6 +34,9 @@ import org.eclipse.jetty.websocket.protocol.OpCode;
*/
public class BaseFrame implements Frame
{
/** Maximum size of Control frame, per RFC 6455 */
public static final int MAX_CONTROL_PAYLOAD = 125;
private boolean fin = false;
private boolean rsv1 = false;
private boolean rsv2 = false;
@ -41,22 +46,85 @@ public class BaseFrame implements Frame
private int payloadLength = 0;
private byte mask[];
private ByteBuffer payload = null;
private boolean continuation = false;
protected int continuationIndex = 0;
/**
* Default constructor
*/
public BaseFrame() {
public BaseFrame()
{
reset();
}
/**
* Construct form opcode
*/
public BaseFrame(OpCode opcode) {
public BaseFrame(OpCode opcode)
{
reset();
this.opcode = opcode;
}
public void assertValid()
{
if (opcode.isControlFrame())
{
if (payloadLength > BaseFrame.MAX_CONTROL_PAYLOAD)
{
throw new ProtocolException("Desired payload length [" + payloadLength + "] exceeds maximum control payload length [" + MAX_CONTROL_PAYLOAD
+ "]");
}
if (fin == false)
{
throw new ProtocolException("Cannot have FIN==false on Control frames");
}
if (rsv1 == false)
{
throw new ProtocolException("Cannot have RSV1==false on Control frames");
}
if (rsv2 == false)
{
throw new ProtocolException("Cannot have RSV2==false on Control frames");
}
if (rsv3 == false)
{
throw new ProtocolException("Cannot have RSV3==false on Control frames");
}
if (isContinuation())
{
throw new ProtocolException("Control frames cannot be Continuations");
}
}
}
@Override
public BaseFrame clone()
{
// TODO: impl
return null;
}
/**
* The number of fragments this frame consists of.
* <p>
* For every {@link OpCode#CONTINUATION} opcode encountered, this increments by one.
* <p>
* Note: Not part of the Base Framing Protocol / header information.
*
* @return the number of continuation fragments encountered.
*/
public int getContinuationIndex()
{
return continuationIndex;
}
@Override
public byte[] getMask()
{
@ -102,7 +170,7 @@ public class BaseFrame implements Frame
public boolean isContinuation()
{
return false; // always false here
return continuation;
}
@Override
@ -150,6 +218,18 @@ public class BaseFrame implements Frame
masked = false;
payloadLength = 0;
mask = null;
continuationIndex = 0;
continuation = false;
}
public void setContinuation(boolean continuation)
{
this.continuation = continuation;
}
public void setContinuationIndex(int continuationIndex)
{
this.continuationIndex = continuationIndex;
}
public void setFin(boolean fin)
@ -181,6 +261,13 @@ public class BaseFrame implements Frame
*/
public void setPayload(byte buf[])
{
if (opcode.isControlFrame())
{
if (buf.length > BaseFrame.MAX_CONTROL_PAYLOAD)
{
throw new ProtocolException("Control Payloads can not exceed 125 bytes in length.");
}
}
int len = buf.length;
this.payload = ByteBuffer.allocate(len);
this.payload.put(buf,0,len);
@ -196,6 +283,14 @@ public class BaseFrame implements Frame
*/
public void setPayload(byte buf[], int offset, int len)
{
if (opcode.isControlFrame())
{
if (len > BaseFrame.MAX_CONTROL_PAYLOAD)
{
throw new ProtocolException("Control Payloads can not exceed 125 bytes in length.");
}
}
this.payload = ByteBuffer.allocate(len);
this.payload.put(buf,offset,len);
this.payload.flip(); // make payload readable
@ -210,6 +305,14 @@ public class BaseFrame implements Frame
*/
public void setPayload(ByteBuffer payload)
{
if (opcode.isControlFrame())
{
if (payload.position() > BaseFrame.MAX_CONTROL_PAYLOAD)
{
throw new ProtocolException("Control Payloads can not exceed 125 bytes in length.");
}
}
this.payload = payload;
this.payload.flip(); // make payload readable
setPayloadLength(this.payload.remaining());

View File

@ -1,151 +0,0 @@
package org.eclipse.jetty.websocket.frames;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.protocol.OpCode;
/**
* Representation of a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">Close Frame (0x08)</a>.
*/
public class CloseFrame extends ControlFrame
{
public static final int MAX_REASON = ControlFrame.MAX_PAYLOAD - 2;
/**
* Construct CloseFrame with no status code or reason
*/
public CloseFrame()
{
super(OpCode.CLOSE);
}
/**
* Construct CloseFrame with status code and no reason
*/
public CloseFrame(int statusCode)
{
super(OpCode.CLOSE);
constructPayload(statusCode,null);
}
/**
* Construct CloseFrame with status code and reason
*/
public CloseFrame(int statusCode, String reason)
{
super(OpCode.CLOSE);
constructPayload(statusCode,reason);
}
public void assertValidPayload(int statusCode, String reason)
{
if ((statusCode < StatusCode.NORMAL) || (statusCode >= 5000))
{
throw new ProtocolException("Status Codes must be in the range 1000 - 5000");
}
if ((reason != null) && (reason.length() > 123))
{
throw new ProtocolException("Reason must not exceed 123 characters.");
}
// TODO add check for invalid utf-8
}
public void assertValidPerPolicy(WebSocketBehavior behavior)
{
int code = getStatusCode();
if ((code < StatusCode.NORMAL) || (code == StatusCode.UNDEFINED) || (code == StatusCode.NO_CLOSE) || (code == StatusCode.NO_CODE)
|| ((code > 1011) && (code <= 2999)) || (code >= 5000))
{
throw new ProtocolException("Invalid close code: " + code);
}
}
private void constructPayload(int statusCode, String reason)
{
assertValidPayload(statusCode,reason);
byte utf[] = null;
int len = 2; // status code
if (StringUtil.isNotBlank(reason))
{
utf = reason.getBytes(StringUtil.__UTF8_CHARSET);
len += utf.length;
}
ByteBuffer payload = ByteBuffer.allocate(len);
payload.putChar((char)statusCode);
if (utf != null)
{
payload.put(utf,0,utf.length);
}
setPayload(payload);
}
public String getReason()
{
if (getPayloadLength() <= 2)
{
return null;
}
ByteBuffer payload = getPayload();
int len = getPayloadLength() - 2;
byte utf[] = new byte[len];
for (int i = 0; i < len; i++)
{
utf[i] = payload.get(i + 2);
}
return StringUtil.toUTF8String(utf,0,utf.length);
}
public int getStatusCode()
{
if (getPayloadLength() < 2)
{
return 0; // no status code
}
int statusCode = 0;
ByteBuffer payload = getPayload();
statusCode |= (payload.get(0) & 0xFF) << 8;
statusCode |= (payload.get(1) & 0xFF);
return statusCode;
}
public boolean hasReason()
{
return getPayloadLength() > 2;
}
@Override
public void setPayload(byte[] buf)
{
super.setPayload(buf);
assertValidPayload(getStatusCode(),getReason());
}
@Override
public void setPayload(ByteBuffer payload)
{
super.setPayload(payload);
assertValidPayload(getStatusCode(),getReason());
}
@Override
public String toString()
{
StringBuilder b = new StringBuilder();
b.append("CloseFrame[");
b.append("len=").append(getPayloadLength());
b.append(",statusCode=").append(getStatusCode());
b.append(",reason=").append(getReason());
b.append("]");
return b.toString();
}
}

View File

@ -1,87 +0,0 @@
package org.eclipse.jetty.websocket.frames;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.protocol.OpCode;
public abstract class ControlFrame extends BaseFrame
{
public static final int MAX_PAYLOAD = 125;
public ControlFrame()
{
super();
super.setFin(true);
}
public ControlFrame(OpCode opcode)
{
super(opcode);
super.setFin(true);
}
@Override
public boolean isContinuation()
{
return false; // no control frames can be continuation
}
@Override
public void setFin(boolean fin)
{
if (!fin)
{
throw new IllegalArgumentException("Cannot set FIN to off on a " + getOpCode().name());
}
}
@Override
public void setPayload(byte[] buf)
{
if (buf.length > MAX_PAYLOAD)
{
throw new ProtocolException("Control Payloads can not exceed 125 bytes in length.");
}
super.setPayload(buf);
}
@Override
public void setPayload(ByteBuffer payload)
{
if (payload.position() > MAX_PAYLOAD)
{
throw new ProtocolException("Control Payloads can not exceed 125 bytes in length.");
}
super.setPayload(payload);
}
@Override
public void setRsv1(boolean rsv1)
{
if (rsv1)
{
throw new IllegalArgumentException("Cannot set RSV1 to true on a " + getOpCode().name());
}
}
@Override
public void setRsv2(boolean rsv2)
{
if (rsv2)
{
throw new IllegalArgumentException("Cannot set RSV2 to true on a " + getOpCode().name());
}
}
@Override
public void setRsv3(boolean rsv3)
{
if (rsv3)
{
throw new IllegalArgumentException("Cannot set RSV3 to true on a " + getOpCode().name());
}
}
}

View File

@ -1,90 +0,0 @@
package org.eclipse.jetty.websocket.frames;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.protocol.OpCode;
public class DataFrame extends BaseFrame
{
public class BinaryFrame extends DataFrame
{
public BinaryFrame(byte[] payload)
{
super(OpCode.BINARY);
super.setPayload(payload);
}
public BinaryFrame(ByteBuffer payload)
{
super(OpCode.BINARY);
super.setPayload(payload);
}
}
public class TextFrame extends DataFrame
{
public TextFrame(String message)
{
super(OpCode.TEXT);
super.setPayload(message.getBytes());
}
public String getPayloadUTF8()
{
return new String(getPayloadData(),StringUtil.__UTF8_CHARSET);
}
}
// internal tracking
private int continuationIndex = 0;
private boolean continuation = false;
public DataFrame()
{
super();
}
public DataFrame(OpCode opcode)
{
super(opcode);
}
/**
* The number of fragments this frame consists of.
* <p>
* For every {@link OpCode#CONTINUATION} opcode encountered, this increments by one.
* <p>
* Note: Not part of the Base Framing Protocol / header information.
*
* @return the number of continuation fragments encountered.
*/
public int getContinuationIndex()
{
return continuationIndex;
}
@Override
public boolean isContinuation()
{
return continuation;
}
@Override
public void reset()
{
super.reset();
continuationIndex = 0;
}
public void setContinuation(boolean continuation)
{
this.continuation = continuation;
}
public void setContinuationIndex(int continuationIndex)
{
this.continuationIndex = continuationIndex;
}
}

View File

@ -1,48 +0,0 @@
package org.eclipse.jetty.websocket.frames;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.protocol.OpCode;
/**
* Representation of a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">Ping Frame (0x09)</a>.
*/
public class PingFrame extends ControlFrame
{
/**
* Default constructor
*/
public PingFrame()
{
super(OpCode.PING);
}
/**
* Construct Ping Frame from known byte[]
*
* @param payload
*/
public PingFrame(byte[] payload)
{
this();
setPayload(payload);
}
@Override
public String toString()
{
StringBuilder b = new StringBuilder();
b.append("PingFrame[");
b.append("len=").append(getPayloadLength());
if (hasPayload())
{
b.append(",payload=");
b.append(BufferUtil.toSummaryString(getPayload()));
}
else
{
b.append(",no-payload");
}
b.append("]");
return b.toString();
}
}

View File

@ -1,69 +0,0 @@
package org.eclipse.jetty.websocket.frames;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.protocol.OpCode;
/**
* Representation of a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">Pong Frame (0x0A)</a>.
*/
public class PongFrame extends ControlFrame
{
/**
* Default constructor
*/
public PongFrame()
{
super(OpCode.PONG);
}
/**
* Construct Pong frame from known byteBuffer
*
* @param payload
*/
public PongFrame(ByteBuffer payload)
{
this();
setPayload(payload);
}
/**
* Construct appropriate PongFrame from PingFrame
*
* @param ping
* the ping frame to base pong from
*/
public PongFrame(PingFrame ping)
{
this();
if (ping.isMasked())
{
int mlen = ping.getMask().length;
byte maskCopy[] = new byte[mlen];
System.arraycopy(ping.getMask(),0,maskCopy,0,mlen);
this.setMask(maskCopy);
}
setPayload(ping.getPayload());
}
@Override
public String toString()
{
StringBuilder b = new StringBuilder();
b.append("PongFrame[");
b.append("len=").append(getPayloadLength());
if (hasPayload())
{
b.append(",payload=");
b.append(BufferUtil.toSummaryString(getPayload()));
}
else
{
b.append(",no-payload");
}
b.append("]");
return b.toString();
}
}

View File

@ -2,12 +2,11 @@ package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.CloseFrame;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.util.CloseUtil;
public class CloseFrameGenerator extends FrameGenerator<CloseFrame>
public class CloseFrameGenerator extends FrameGenerator
{
public CloseFrameGenerator(WebSocketPolicy policy)
{
@ -15,25 +14,9 @@ public class CloseFrameGenerator extends FrameGenerator<CloseFrame>
}
@Override
public void fillPayload(ByteBuffer buffer, CloseFrame close)
public void fillPayload(ByteBuffer buffer, BaseFrame close)
{
if ( close.getStatusCode() != 0 )
{
buffer.putChar((char)close.getStatusCode()); // char is unsigned 16
// payload requires a status code in order to be written
if ( close.hasPayload() )
{
if (close.hasReason())
{
byte utf[] = close.getReason().getBytes(StringUtil.__UTF8_CHARSET);
buffer.put(utf,0,utf.length);
}
}
}
else if (close.hasPayload())
{
throw new ProtocolException("Close frames require setting a status code if using payload.");
}
CloseUtil.assertValidPayload(close.getPayload());
super.fillPayload(buffer,close);
}
}

View File

@ -1,21 +0,0 @@
package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.DataFrame;
public class DataFrameGenerator extends FrameGenerator<DataFrame>
{
public DataFrameGenerator(WebSocketPolicy policy)
{
super(policy);
}
@Override
public void fillPayload(ByteBuffer buffer, DataFrame binary)
{
BufferUtil.put(binary.getPayload(),buffer);
}
}

View File

@ -2,6 +2,7 @@ package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer;
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.api.PolicyViolationException;
@ -33,7 +34,7 @@ import org.eclipse.jetty.websocket.protocol.OpCode;
*
* @param <T>
*/
public abstract class FrameGenerator<T extends BaseFrame>
public class FrameGenerator
{
private static final Logger LOG = Log.getLogger(FrameGenerator.class);
@ -43,14 +44,17 @@ public abstract class FrameGenerator<T extends BaseFrame>
public static final int OVERHEAD = 28;
private final WebSocketPolicy policy;
protected FrameGenerator(WebSocketPolicy policy)
public FrameGenerator(WebSocketPolicy policy)
{
this.policy = policy;
}
public abstract void fillPayload(ByteBuffer buffer, T frame);
public void fillPayload(ByteBuffer buffer, BaseFrame frame)
{
BufferUtil.put(frame.getPayload(),buffer);
}
public ByteBuffer generate(ByteBuffer buffer, T frame)
public ByteBuffer generate(ByteBuffer buffer, BaseFrame frame)
{
LOG.debug(String.format("Generate.Frame[opcode=%s,fin=%b,cont=%b,rsv1=%b,rsv2=%b,rsv3=%b,mask=%b,plength=%d]",frame.getOpCode().toString(),
frame.isFin(),frame.isContinuation(),frame.isRsv1(),frame.isRsv2(),frame.isRsv3(),frame.isMasked(),frame.getPayloadLength()));

View File

@ -38,19 +38,15 @@ public class Generator
{
private static final Logger LOG = Log.getLogger(Generator.class);
private final EnumMap<OpCode, FrameGenerator<?>> generators = new EnumMap<>(OpCode.class);
private final EnumMap<OpCode, FrameGenerator> generators = new EnumMap<>(OpCode.class);
private final FrameGenerator basicGenerator;
public Generator(WebSocketPolicy policy)
{
generators.put(OpCode.TEXT,new DataFrameGenerator(policy));
generators.put(OpCode.BINARY,new DataFrameGenerator(policy));
generators.put(OpCode.PING,new PingFrameGenerator(policy));
generators.put(OpCode.PONG,new PongFrameGenerator(policy));
generators.put(OpCode.CLOSE,new CloseFrameGenerator(policy));
basicGenerator = new FrameGenerator(policy);
}
@SuppressWarnings(
{ "unchecked", "rawtypes" })
public ByteBuffer generate(ByteBuffer buffer, BaseFrame frame)
{
if (LOG.isDebugEnabled())
@ -58,6 +54,11 @@ public class Generator
LOG.debug("To Generate: {}",frame);
}
FrameGenerator generator = generators.get(frame.getOpCode());
if (generator == null)
{
// no specific generator? use default
generator = basicGenerator;
}
ByteBuffer ret = generator.generate(buffer,frame);
if (LOG.isDebugEnabled())
{

View File

@ -1,24 +0,0 @@
package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.PingFrame;
public class PingFrameGenerator extends FrameGenerator<PingFrame>
{
public PingFrameGenerator(WebSocketPolicy policy)
{
super(policy);
}
@Override
public void fillPayload(ByteBuffer buffer, PingFrame ping)
{
if ( ping.hasPayload() )
{
BufferUtil.put(ping.getPayload(),buffer);
}
}
}

View File

@ -1,21 +0,0 @@
package org.eclipse.jetty.websocket.generator;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.PongFrame;
public class PongFrameGenerator extends FrameGenerator<PongFrame>
{
public PongFrameGenerator(WebSocketPolicy policy)
{
super(policy);
}
@Override
public void fillPayload(ByteBuffer buffer, PongFrame pong)
{
BufferUtil.put(pong.getPayload(),buffer);
}
}

View File

@ -20,12 +20,12 @@ import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.callbacks.WebSocketCloseCallback;
import org.eclipse.jetty.websocket.frames.CloseFrame;
import org.eclipse.jetty.websocket.frames.DataFrame;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.generator.FrameGenerator;
import org.eclipse.jetty.websocket.generator.Generator;
import org.eclipse.jetty.websocket.parser.Parser;
import org.eclipse.jetty.websocket.protocol.ExtensionConfig;
import org.eclipse.jetty.websocket.protocol.FrameBuilder;
/**
* Provides the implementation of {@link WebSocketConnection} within the framework of the new {@link AsyncConnection} framework of jetty-io
@ -220,7 +220,7 @@ public class WebSocketAsyncConnection extends AbstractAsyncConnection implements
*/
private void terminateConnection(int statusCode, String reason)
{
CloseFrame close = new CloseFrame(statusCode,reason);
BaseFrame close = FrameBuilder.close(statusCode,reason).asFrame();
// fire and forget -> close frame
ByteBuffer buf = bufferPool.acquire(policy.getBufferSize(),false);
@ -253,9 +253,8 @@ public class WebSocketAsyncConnection extends AbstractAsyncConnection implements
}
ByteBuffer raw = bufferPool.acquire(len + FrameGenerator.OVERHEAD,false);
BufferUtil.clearToFill(raw);
DataFrame frame = new DataFrame();
frame.setPayload(ByteBuffer.wrap(buf,offset,len));
frame.setFin(true);
BaseFrame frame = FrameBuilder.binary(buf,offset,len).fin(true).asFrame();
generator.generate(raw,frame);
BufferUtil.flipToFlush(raw,0);
writeRaw(context,callback,raw);
@ -280,9 +279,8 @@ public class WebSocketAsyncConnection extends AbstractAsyncConnection implements
ByteBuffer raw[] = new ByteBuffer[messages.length];
for (int i = 0; i < len; i++)
{
DataFrame frame = new DataFrame();
frame.setPayload(ByteBuffer.wrap(messages[i].getBytes()));
frame.setFin(true);
BaseFrame frame = FrameBuilder.text(messages[i]).fin(true).asFrame();
raw[i] = bufferPool.acquire(policy.getBufferSize(),false);
BufferUtil.clearToFill(raw[i]);
generator.generate(raw[i],frame);

View File

@ -1,66 +0,0 @@
package org.eclipse.jetty.websocket.parser;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.DataFrame;
/**
* Parsing for the {@link BinaryFrame}.
*/
public class BinaryPayloadParser extends FrameParser<DataFrame>
{
private DataFrame frame;
private ByteBuffer payload;
private int payloadLength;
public BinaryPayloadParser(WebSocketPolicy policy)
{
super(policy);
frame = new DataFrame();
}
@Override
public DataFrame getFrame()
{
return frame;
}
@Override
public DataFrame newFrame()
{
frame = new DataFrame();
return frame;
}
@Override
public boolean parsePayload(ByteBuffer buffer)
{
payloadLength = getFrame().getPayloadLength();
while (buffer.hasRemaining())
{
if (payload == null)
{
getPolicy().assertValidBinaryMessageSize(payloadLength);
payload = ByteBuffer.allocate(payloadLength);
}
copyBuffer(buffer,payload,payload.remaining());
if (payload.position() >= payloadLength)
{
frame.setPayload(payload);
this.payload = null;
return true;
}
}
return false;
}
@Override
public void reset()
{
super.reset();
payload = null;
}
}

View File

@ -1,83 +0,0 @@
package org.eclipse.jetty.websocket.parser;
import java.nio.ByteBuffer;
import javax.xml.ws.ProtocolException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.CloseFrame;
/**
* Parsing for the {@link CloseFrame}.
*/
public class ClosePayloadParser extends FrameParser<CloseFrame>
{
private CloseFrame frame;
private ByteBuffer payload;
private int payloadLength;
public ClosePayloadParser(WebSocketPolicy policy)
{
super(policy);
frame = new CloseFrame();
}
@Override
public CloseFrame getFrame()
{
return frame;
}
@Override
public CloseFrame newFrame()
{
frame = new CloseFrame();
return frame;
}
@Override
public boolean parsePayload(ByteBuffer buffer)
{
payloadLength = getFrame().getPayloadLength();
if (payloadLength == 0)
{
// no status code. no reason.
return true;
}
/*
* invalid payload length.
*/
if ((payloadLength == 1) || (payloadLength > 125))
{
throw new ProtocolException("Close: invalid payload length: " + payloadLength);
}
if (payload == null)
{
getPolicy().assertValidTextMessageSize(payloadLength);
payload = ByteBuffer.allocate(payloadLength);
}
while (buffer.hasRemaining())
{
copyBuffer(buffer,payload,payload.remaining());
if (payload.position() >= payloadLength)
{
frame.setPayload(payload);
frame.assertValidPerPolicy(getPolicy().getBehavior());
return true;
}
}
return false;
}
@Override
public void reset()
{
super.reset();
payloadLength = 0;
payload = null;
}
}

View File

@ -32,7 +32,7 @@ import org.eclipse.jetty.websocket.protocol.OpCode;
* +---------------------------------------------------------------+
* </pre>
*/
public abstract class FrameParser<T extends BaseFrame>
public class FrameParser
{
private enum State
{
@ -45,9 +45,15 @@ public abstract class FrameParser<T extends BaseFrame>
private static final Logger LOG = Log.getLogger(FrameParser.class);
private WebSocketPolicy policy;
// State specific
private State state = State.PAYLOAD_LEN;
private long length = 0;
private int cursor = 0;
// Frame
private BaseFrame frame;
// payload specific
private ByteBuffer payload;
private int payloadLength;
public FrameParser(WebSocketPolicy policy)
{
@ -68,7 +74,7 @@ public abstract class FrameParser<T extends BaseFrame>
protected int copyBuffer(ByteBuffer src, ByteBuffer dest, int length)
{
int amt = Math.min(length,src.remaining());
if (getFrame().isMasked())
if (frame.isMasked())
{
// Demask the content 1 byte at a time
byte mask[] = getFrame().getMask();
@ -93,7 +99,10 @@ public abstract class FrameParser<T extends BaseFrame>
*
* @return the frame that is being parsed. should always return an object (never null)
*/
public abstract T getFrame();
public BaseFrame getFrame()
{
return frame;
}
protected WebSocketPolicy getPolicy()
{
@ -111,7 +120,7 @@ public abstract class FrameParser<T extends BaseFrame>
*/
public final void initFrame(boolean fin, boolean rsv1, boolean rsv2, boolean rsv3, OpCode opcode)
{
T frame = newFrame();
BaseFrame frame = new BaseFrame();
frame.setFin(fin);
frame.setRsv1(rsv1);
frame.setRsv2(rsv2);
@ -119,8 +128,6 @@ public abstract class FrameParser<T extends BaseFrame>
frame.setOpCode(opcode);
}
public abstract T newFrame();
/**
* Parse the base framing protocol buffer.
* <p>
@ -238,7 +245,29 @@ public abstract class FrameParser<T extends BaseFrame>
* the payload buffer
* @return true if payload is done reading, false if incomplete
*/
public abstract boolean parsePayload(ByteBuffer buffer);
public boolean parsePayload(ByteBuffer buffer)
{
payloadLength = getFrame().getPayloadLength();
while (buffer.hasRemaining())
{
if (payload == null)
{
getPolicy().assertValidPayloadLength(payloadLength);
frame.assertValid();
payload = ByteBuffer.allocate(payloadLength);
}
copyBuffer(buffer,payload,payload.remaining());
if (payload.position() >= payloadLength)
{
frame.setPayload(payload);
this.payload = null;
return true;
}
}
return false;
}
/**
* Reset the frame and parser states

View File

@ -1,7 +1,6 @@
package org.eclipse.jetty.websocket.parser;
import java.nio.ByteBuffer;
import java.util.EnumMap;
import java.util.EventListener;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@ -13,6 +12,7 @@ import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.protocol.OpCode;
import org.eclipse.jetty.websocket.util.CloseUtil;
/**
* Parsing of a frames in WebSocket land.
@ -35,8 +35,7 @@ public class Parser
private static final Logger LOG = Log.getLogger(Parser.class);
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
private final EnumMap<OpCode, FrameParser<?>> parsers = new EnumMap<>(OpCode.class);
private FrameParser<?> parser;
private final FrameParser parser;
private WebSocketPolicy policy;
private State state = State.FINOP;
@ -47,14 +46,8 @@ public class Parser
*/
this.policy = wspolicy;
this.parser = new FrameParser(wspolicy);
reset();
parsers.put(OpCode.TEXT,new TextPayloadParser(policy));
parsers.put(OpCode.BINARY,new BinaryPayloadParser(policy));
parsers.put(OpCode.CLOSE,new ClosePayloadParser(policy));
parsers.put(OpCode.PING,new PingPayloadParser(policy));
parsers.put(OpCode.PONG,new PongPayloadParser(policy));
}
public void addListener(Listener listener)
@ -62,6 +55,12 @@ public class Parser
listeners.add(listener);
}
private void assertValidClose()
{
ByteBuffer payload = parser.getFrame().getPayload();
CloseUtil.assertValidPayload(payload);
}
public WebSocketPolicy getPolicy()
{
return policy;
@ -131,7 +130,7 @@ public class Parser
if (opcode == OpCode.CONTINUATION)
{
if (parser == null)
if (parser.getFrame() == null)
{
throw new ProtocolException("Fragment continuation frame without prior !FIN");
}
@ -139,11 +138,6 @@ public class Parser
opcode = parser.getFrame().getOpCode();
}
if (parser == null)
{
// Establish specific type parser and hand off to them.
parser = parsers.get(opcode);
}
parser.reset();
parser.initFrame(fin,rsv1,rsv2,rsv3,opcode);
@ -162,6 +156,11 @@ public class Parser
{
if (parser.parsePayload(buffer))
{
// special check for close
if (parser.getFrame().getOpCode() == OpCode.CLOSE)
{
assertValidClose();
}
notifyFrame(parser.getFrame());
parser.reset();
if (parser.getFrame().isFin())
@ -176,12 +175,11 @@ public class Parser
}
/*
* if the payload was empty we could end up in this state
* because there was no remaining bits to process
* if the payload was empty we could end up in this state because there was no remaining bits to process
*/
if ( state == State.PAYLOAD )
if (state == State.PAYLOAD)
{
notifyFrame( parser.getFrame() );
notifyFrame(parser.getFrame());
parser.reset();
if (parser.getFrame().isFin())
{
@ -214,11 +212,7 @@ public class Parser
public void reset()
{
state = State.FINOP;
if (parser != null)
{
parser.reset();
}
parser = null;
parser.reset();
}
@Override

View File

@ -1,65 +0,0 @@
package org.eclipse.jetty.websocket.parser;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.PingFrame;
/**
* Parsing for the {@link PingFrame}.
*/
public class PingPayloadParser extends FrameParser<PingFrame>
{
private PingFrame frame;
private ByteBuffer payload;
private int payloadLength;
public PingPayloadParser(WebSocketPolicy policy)
{
super(policy);
frame = new PingFrame();
}
@Override
public PingFrame getFrame()
{
return frame;
}
@Override
public PingFrame newFrame()
{
frame = new PingFrame();
return frame;
}
@Override
public boolean parsePayload(ByteBuffer buffer)
{
payloadLength = getFrame().getPayloadLength();
while (buffer.hasRemaining())
{
if (payload == null)
{
// TODO: buffer size limits
payload = ByteBuffer.allocate(payloadLength);
}
copyBuffer(buffer,payload,payload.remaining());
if (payload.position() >= payloadLength)
{
frame.setPayload(payload);
return true;
}
}
return false;
}
@Override
public void reset()
{
super.reset();
payload = null;
}
}

View File

@ -1,62 +0,0 @@
package org.eclipse.jetty.websocket.parser;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.PongFrame;
public class PongPayloadParser extends FrameParser<PongFrame>
{
private PongFrame frame;
private ByteBuffer payload;
private int payloadLength;
public PongPayloadParser(WebSocketPolicy policy)
{
super(policy);
frame = new PongFrame();
}
@Override
public PongFrame getFrame()
{
return frame;
}
@Override
public PongFrame newFrame()
{
frame = new PongFrame();
return frame;
}
@Override
public boolean parsePayload(ByteBuffer buffer)
{
payloadLength = getFrame().getPayloadLength();
while (buffer.hasRemaining())
{
if (payload == null)
{
// TODO: buffer size limits
payload = ByteBuffer.allocate(payloadLength);
}
copyBuffer(buffer,payload,payload.remaining());
if (payload.position() >= payloadLength)
{
frame.setPayload(payload);
return true;
}
}
return false;
}
@Override
public void reset()
{
super.reset();
payload = null;
}
}

View File

@ -1,64 +0,0 @@
package org.eclipse.jetty.websocket.parser;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.DataFrame;
public class TextPayloadParser extends FrameParser<DataFrame>
{
private DataFrame frame;
private ByteBuffer payload;
private int payloadLength;
public TextPayloadParser(WebSocketPolicy policy)
{
super(policy);
frame = new DataFrame();
}
@Override
public DataFrame getFrame()
{
return frame;
}
@Override
public DataFrame newFrame()
{
frame = new DataFrame();
return frame;
}
@Override
public boolean parsePayload(ByteBuffer buffer)
{
payloadLength = getFrame().getPayloadLength();
while (buffer.hasRemaining())
{
if (payload == null)
{
getPolicy().assertValidTextMessageSize(payloadLength);
payload = ByteBuffer.allocate(payloadLength);
}
copyBuffer(buffer,payload,payload.remaining());
if (payload.position() >= payloadLength)
{
payload.flip();
frame.setPayload(payload);
return true;
}
}
return false;
}
@Override
public void reset()
{
super.reset();
payloadLength = 0;
payload = null;
}
}

View File

@ -1,42 +0,0 @@
package org.eclipse.jetty.websocket.parser;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.BaseFrame;
public class UnknownPayloadParser extends FrameParser<BaseFrame>
{
private BaseFrame frame;
public UnknownPayloadParser(WebSocketPolicy policy)
{
super(policy);
frame = new BaseFrame();
}
@Override
public BaseFrame getFrame()
{
return frame;
}
@Override
public BaseFrame newFrame()
{
frame = new BaseFrame();
return frame;
}
@Override
public boolean parsePayload(ByteBuffer buffer)
{
return false;
}
@Override
public void reset()
{
super.reset();
}
}

View File

@ -1,10 +1,11 @@
package org.eclipse.jetty.websocket.frames;
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.websocket.api.PolicyViolationException;
import org.eclipse.jetty.websocket.protocol.OpCode;
import org.eclipse.jetty.websocket.frames.BaseFrame;
public class FrameBuilder
@ -26,6 +27,27 @@ public class FrameBuilder
public static FrameBuilder close()
{
return close(-1,null);
}
public static FrameBuilder close(int statusCode)
{
return close(statusCode,null);
}
public static FrameBuilder close(int statusCode, String reason)
{
if (statusCode != (-1))
{
ByteBuffer buf = ByteBuffer.allocate(BaseFrame.MAX_CONTROL_PAYLOAD);
buf.putChar((char)statusCode);
if (StringUtil.isNotBlank(reason))
{
byte utf[] = StringUtil.getUtf8Bytes(reason);
buf.put(utf,0,utf.length);
}
return new FrameBuilder(new BaseFrame(OpCode.CLOSE)).payload(buf);
}
return new FrameBuilder(new BaseFrame(OpCode.CLOSE));
}
@ -80,6 +102,17 @@ public class FrameBuilder
public ByteBuffer asByteBuffer()
{
ByteBuffer buffer = ByteBuffer.allocate(frame.getPayloadLength() + 32 );
fill(buffer);
return buffer;
}
public BaseFrame asFrame()
{
return frame;
}
public void fill(ByteBuffer buffer)
{
byte b;
// Setup fin thru opcode
@ -198,13 +231,6 @@ public class FrameBuilder
}
BufferUtil.flipToFlush(buffer,0);
return buffer;
}
public BaseFrame asFrame()
{
return frame;
}
public FrameBuilder fin( boolean fin )

View File

@ -3,9 +3,26 @@ package org.eclipse.jetty.websocket.util;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.StatusCode;
public class CloseUtil
{
public static void assertValidPayload(ByteBuffer payload)
{
int statusCode = getStatusCode(payload);
// Validate value
if ((statusCode < StatusCode.NORMAL) || (statusCode == StatusCode.UNDEFINED) || (statusCode == StatusCode.NO_CLOSE)
|| (statusCode == StatusCode.NO_CODE) || ((statusCode > 1011) && (statusCode <= 2999)) || (statusCode >= 5000))
{
throw new ProtocolException("Invalid close code: " + statusCode);
}
// validate reason
getReason(payload);
}
public static String getReason(byte[] payload)
{
if (payload.length <= 2)

View File

@ -8,12 +8,12 @@ import org.eclipse.jetty.io.StandardByteBufferPool;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.DataFrame.TextFrame;
import org.eclipse.jetty.websocket.frames.FrameBuilder;
import org.eclipse.jetty.websocket.generator.Generator;
import org.eclipse.jetty.websocket.masks.FixedMasker;
import org.eclipse.jetty.websocket.masks.RandomMasker;
import org.eclipse.jetty.websocket.parser.FrameParseCapture;
import org.eclipse.jetty.websocket.parser.Parser;
import org.eclipse.jetty.websocket.protocol.FrameBuilder;
import org.junit.Assert;
import org.junit.Test;

View File

@ -9,10 +9,10 @@ import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.frames.DataFrame.TextFrame;
import org.eclipse.jetty.websocket.frames.FrameBuilder;
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.protocol.FrameBuilder;
import org.junit.Assert;
import org.junit.Test;

View File

@ -10,10 +10,10 @@ import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.frames.DataFrame.BinaryFrame;
import org.eclipse.jetty.websocket.frames.FrameBuilder;
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.protocol.FrameBuilder;
import org.junit.Assert;
import org.junit.Test;

View File

@ -12,9 +12,9 @@ import org.eclipse.jetty.websocket.examples.AnnotatedFramesSocket;
import org.eclipse.jetty.websocket.examples.ListenerBasicSocket;
import org.eclipse.jetty.websocket.frames.CloseFrame;
import org.eclipse.jetty.websocket.frames.DataFrame.BinaryFrame;
import org.eclipse.jetty.websocket.frames.FrameBuilder;
import org.eclipse.jetty.websocket.frames.PingFrame;
import org.eclipse.jetty.websocket.io.LocalWebSocketConnection;
import org.eclipse.jetty.websocket.protocol.FrameBuilder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;

View File

@ -1,5 +1,6 @@
package org.eclipse.jetty.websocket.frames;
import org.eclipse.jetty.websocket.protocol.FrameBuilder;
import org.junit.Assert;
import org.junit.Test;

View File

@ -8,9 +8,9 @@ import org.eclipse.jetty.websocket.ByteBufferAssert;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.BaseFrame;
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.protocol.FrameBuilder;
import org.junit.Test;
public class RFC6455ExamplesGeneratorTest

View File

@ -15,9 +15,9 @@ 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.DataFrame.TextFrame;
import org.eclipse.jetty.websocket.frames.FrameBuilder;
import org.eclipse.jetty.websocket.frames.PongFrame;
import org.eclipse.jetty.websocket.generator.FrameGenerator;
import org.eclipse.jetty.websocket.protocol.FrameBuilder;
import org.eclipse.jetty.websocket.protocol.OpCode;
import org.eclipse.jetty.websocket.server.ByteBufferAssert;
import org.eclipse.jetty.websocket.server.SimpleServletServer;

View File

@ -17,8 +17,8 @@ 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.FrameBuilder;
import org.eclipse.jetty.websocket.protocol.OpCode;
import org.eclipse.jetty.websocket.server.SimpleServletServer;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;