Next step in simplifying the frames
This commit is contained in:
parent
b515e845cc
commit
dfc9315bc7
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 )
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue