From b9ca387d531bdb8b400cf9d62888b1c1093e4291 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Mon, 18 Jun 2012 13:42:47 -0700 Subject: [PATCH] Cleaning up 'frames' package --- .../websocket/WebSocketGeneratorRFC6455.java | 2 +- .../websocket/WebSocketParserRFC6455.java | 6 +- .../jetty/websocket/api/WebSocket.java | 26 +++---- .../jetty/websocket/frames/BaseFrame.java | 67 ++++++++++++++----- .../jetty/websocket/frames/BinaryFrame.java | 66 +++++++++++++++++- .../jetty/websocket/frames/CloseFrame.java | 46 ++++++++++--- .../jetty/websocket/frames/ControlFrame.java | 31 ++++----- .../jetty/websocket/frames/PingFrame.java | 9 +-- .../jetty/websocket/frames/PongFrame.java | 11 +-- .../jetty/websocket/frames/TextFrame.java | 62 ++++++++++++++++- 10 files changed, 251 insertions(+), 75 deletions(-) diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorRFC6455.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorRFC6455.java index a572646c44b..bd4bbefdd5c 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorRFC6455.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorRFC6455.java @@ -86,7 +86,7 @@ public class WebSocketGeneratorRFC6455 implements WebSocketGenerator boolean mask=_maskGen!=null; if (_buffer==null) - _buffer=mask?_buffers.getBuffer():_buffers.getDirectBuffer(); + _buffer=mask?_buffers.getData():_buffers.getDirectBuffer(); boolean last=WebSocketConnectionRFC6455.isLastFrame(flags); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455.java index d4020d98f07..d12f2f8519f 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketParserRFC6455.java @@ -82,7 +82,7 @@ public class WebSocketParserRFC6455 implements WebSocketParser /* ------------------------------------------------------------ */ /** - * @param buffers The buffers to use for parsing. Only the {@link Buffers#getBuffer()} is used. + * @param buffers The buffers to use for parsing. Only the {@link Buffers#getData()} is used. * This should be a direct buffer if binary data is mostly used or an indirect buffer if utf-8 data * is mostly used. * @param endp the endpoint @@ -139,7 +139,7 @@ public class WebSocketParserRFC6455 implements WebSocketParser public int parseNext() { if (_buffer==null) - _buffer=_buffers.getBuffer(); + _buffer=_buffers.getData(); boolean progress=false; int filled=-1; @@ -374,7 +374,7 @@ public class WebSocketParserRFC6455 implements WebSocketParser if (buffer!=null && buffer.length()>0) { if (_buffer==null) - _buffer=_buffers.getBuffer(); + _buffer=_buffers.getData(); _buffer.put(buffer); buffer.clear(); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocket.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocket.java index ca89e6d0920..68938e71fd7 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocket.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocket.java @@ -23,19 +23,19 @@ public class WebSocket */ private final static byte[] MAGIC; - public final static int CLOSE_NORMAL = 1000; - public final static int CLOSE_SHUTDOWN = 1001; - public final static int CLOSE_PROTOCOL = 1002; - public final static int CLOSE_BAD_DATA = 1003; - public final static int CLOSE_UNDEFINED = 1004; - public final static int CLOSE_NO_CODE = 1005; - public final static int CLOSE_NO_CLOSE = 1006; - public final static int CLOSE_BAD_PAYLOAD = 1007; - public final static int CLOSE_POLICY_VIOLATION = 1008; - public final static int CLOSE_MESSAGE_TOO_LARGE = 1009; - public final static int CLOSE_REQUIRED_EXTENSION = 1010; - public final static int CLOSE_SERVER_ERROR = 1011; - public final static int CLOSE_FAILED_TLS_HANDSHAKE = 1015; + public final static short CLOSE_NORMAL = 1000; + public final static short CLOSE_SHUTDOWN = 1001; + public final static short CLOSE_PROTOCOL = 1002; + public final static short CLOSE_BAD_DATA = 1003; + public final static short CLOSE_UNDEFINED = 1004; + public final static short CLOSE_NO_CODE = 1005; + public final static short CLOSE_NO_CLOSE = 1006; + public final static short CLOSE_BAD_PAYLOAD = 1007; + public final static short CLOSE_POLICY_VIOLATION = 1008; + public final static short CLOSE_MESSAGE_TOO_LARGE = 1009; + public final static short CLOSE_REQUIRED_EXTENSION = 1010; + public final static short CLOSE_SERVER_ERROR = 1011; + public final static short CLOSE_FAILED_TLS_HANDSHAKE = 1015; static { diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BaseFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BaseFrame.java index 27d9f631bd3..01d4509a9b9 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BaseFrame.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BaseFrame.java @@ -26,16 +26,42 @@ package org.eclipse.jetty.websocket.frames; */ public class BaseFrame { + /** + * OpCode for a {@link ContinuationFrame} + * + * @see RFC 6455, Section 11.8 (WebSocket Opcode Registry + */ public final static byte OP_CONTINUATION = 0x00; + /** + * OpCode for a {@link TextFrame} + * + * @see RFC 6455, Section 11.8 (WebSocket Opcode Registry + */ public final static byte OP_TEXT = 0x01; + /** + * OpCode for a {@link BinaryFrame} + * + * @see RFC 6455, Section 11.8 (WebSocket Opcode Registry + */ public final static byte OP_BINARY = 0x02; - public final static byte OP_EXT_DATA = 0x03; - - public final static byte OP_CONTROL = 0x08; + /** + * OpCode for a {@link CloseFrame} + * + * @see RFC 6455, Section 11.8 (WebSocket Opcode Registry + */ public final static byte OP_CLOSE = 0x08; + /** + * OpCode for a {@link PingFrame} + * + * @see RFC 6455, Section 11.8 (WebSocket Opcode Registry + */ public final static byte OP_PING = 0x09; + /** + * OpCode for a {@link PongFrame} + * + * @see RFC 6455, Section 11.8 (WebSocket Opcode Registry + */ public final static byte OP_PONG = 0x0A; - public final static byte OP_EXT_CTRL = 0x0B; private boolean fin; private boolean rsv1; @@ -43,30 +69,35 @@ public class BaseFrame private boolean rsv3; private byte opcode = -1; private boolean masked = false; + private long payloadLength; private byte mask[]; - public final static int FLAG_FIN = 0x8; public final static int FLAG_RSV1 = 0x4; public final static int FLAG_RSV2 = 0x2; public final static int FLAG_RSV3 = 0x1; - /** - * @deprecated use {@link #isControlFrame()} instead - */ - @Deprecated - public static boolean isControlFrame(byte opcode) - { - return (opcode & OP_CONTROL) != 0; + public BaseFrame() { + /* default */ } /** - * @deprecated use {@link #isLastFrame()} instead + * Copy Constructor + * @param copy the copy */ - @Deprecated - public static boolean isLastFrame(byte flags) - { - return (flags & FLAG_FIN) != 0; + public BaseFrame(BaseFrame copy) { + this.fin = copy.fin; + this.rsv1 = copy.rsv1; + this.rsv2 = copy.rsv2; + this.rsv3 = copy.rsv3; + this.opcode = copy.opcode; + this.masked = copy.masked; + this.payloadLength = copy.payloadLength; + if(copy.mask != null) { + int mlen = copy.mask.length; + this.mask = new byte[mlen]; + System.arraycopy(copy.mask,0,this.mask,0,mlen); + } } public byte[] getMask() @@ -90,7 +121,7 @@ public class BaseFrame public boolean isControlFrame() { - return (opcode & OP_CONTROL) != 0; + return (opcode >= OP_CLOSE); } public boolean isFin() diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BinaryFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BinaryFrame.java index 3023fd3d5d5..f346aeb8220 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BinaryFrame.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BinaryFrame.java @@ -1,5 +1,69 @@ package org.eclipse.jetty.websocket.frames; -public class BinaryFrame { +import java.nio.ByteBuffer; +/** + * Representation of a Binary Data Frame (0x02). + */ +public class BinaryFrame extends BaseFrame +{ + private ByteBuffer data; // TODO: make this a standard byte buffer? + + /** + * Default unspecified data + */ + public BinaryFrame() + { + super(); + super.setOpcode(OP_BINARY); + } + + /** + * Copy Constructor + * + * @param base + * the base frame to work off of. + */ + public BinaryFrame(BaseFrame base) + { + super(base); + // TODO: limit this somehow? + // TODO: create a streaming binary frame? + data = ByteBuffer.allocate((int)base.getPayloadLength()); + } + + /** + * Get the data + * + * @return the raw bytebuffer data (can be null) + */ + public ByteBuffer getData() + { + return data; + } + + /** + * Set the data and payload length. + * + * @param buf + * the bytebuffer to set + */ + public void setData(byte buf[]) + { + int len = buf.length; + this.data = ByteBuffer.allocate(len); + this.setPayloadLength(len); + } + + /** + * Set the data and payload length. + * + * @param buf + * the byte array to set + */ + public void setData(ByteBuffer buffer) + { + this.data = buffer; + this.setPayloadLength(buffer.capacity()); + } } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/CloseFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/CloseFrame.java index 7416b70ba53..531850b55c0 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/CloseFrame.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/CloseFrame.java @@ -1,26 +1,52 @@ package org.eclipse.jetty.websocket.frames; -import org.eclipse.jetty.websocket.frames.ControlFrameType; +import org.eclipse.jetty.websocket.api.WebSocket; -public class CloseFrame extends ControlFrame +/** + * Representation of a Close Frame (0x08). + */ +public class CloseFrame extends ControlFrame { - private final int pingId; + private final short statusCode; + private String reason; - public CloseFrame(short version, int pingId) + public CloseFrame() { - super(version, ControlFrameType.CLOSE_FRAME, (byte)0); - this.pingId = pingId; + this(WebSocket.CLOSE_NORMAL); // TODO: evaluate default (or unspecified status code) } - public int getPingId() + public CloseFrame(short statusCode) { - return pingId; + super(ControlFrameType.CLOSE_FRAME); + this.statusCode = statusCode; + } + + public String getReason() + { + return reason; + } + + public short getStatusCode() + { + return statusCode; + } + + public void setReason(String reason) + { + this.reason = reason; } @Override public String toString() { - return String.format("%s ping=%d", super.toString(), getPingId()); + StringBuilder msg = new StringBuilder(); + msg.append(super.toString()); + msg.append(" statusCode=").append(statusCode); + if (reason != null) + { + msg.append(" reason=\"").append(reason).append("\""); + } + + return msg.toString(); } - } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/ControlFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/ControlFrame.java index 30c37883507..13b0ca5e7e3 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/ControlFrame.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/ControlFrame.java @@ -1,34 +1,27 @@ package org.eclipse.jetty.websocket.frames; -import org.eclipse.jetty.websocket.frames.ControlFrameType; - -public class ControlFrame extends BaseFrame +/** + * Base class for all control frames. + *

+ * TODO: investigate as candidate for removal. + */ +public abstract class ControlFrame extends BaseFrame { - private final short _version; - private final ControlFrameType _type; - private final byte _flags; // check if needed + private final ControlFrameType type; - - public ControlFrame( short version, ControlFrameType type, byte flags ) + public ControlFrame(ControlFrameType type) { - _version = version; - _type = type; - _flags = flags; - } - - public short getVersion() - { - return _version; + this.type = type; } public ControlFrameType getType() { - return _type; + return type; } - + @Override public String toString() { - return String.format("%s frame v%s", getType(), getVersion()); + return String.format("%s frame v%s",getType()); } } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/PingFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/PingFrame.java index a802e23ef43..a3cc8a767a9 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/PingFrame.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/PingFrame.java @@ -1,14 +1,15 @@ package org.eclipse.jetty.websocket.frames; -import org.eclipse.jetty.websocket.frames.ControlFrameType; - +/** + * Representation of a Ping Frame (0x09). + */ public class PingFrame extends ControlFrame { private final int pingId; - public PingFrame(short version, int pingId) + public PingFrame(int pingId) { - super(version, ControlFrameType.PING_FRAME, (byte)0); + super(ControlFrameType.PING_FRAME); this.pingId = pingId; } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/PongFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/PongFrame.java index 63d41d8f66d..89431f9f559 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/PongFrame.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/PongFrame.java @@ -1,14 +1,15 @@ package org.eclipse.jetty.websocket.frames; -import org.eclipse.jetty.websocket.frames.ControlFrameType; - +/** + * Representation of a Pong Frame (0x0A). + */ public class PongFrame extends ControlFrame { private final int pingId; - public PongFrame(short version, int pingId) + public PongFrame(int pingId) { - super(version, ControlFrameType.PONG_FRAME, (byte)0); + super(ControlFrameType.PONG_FRAME); this.pingId = pingId; } @@ -20,6 +21,6 @@ public class PongFrame extends ControlFrame @Override public String toString() { - return String.format("%s ping=%d", super.toString(), getPingId()); + return String.format("%s pong=%d",super.toString(),getPingId()); } } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/TextFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/TextFrame.java index e1ceb180ed1..676a3f7df4d 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/TextFrame.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/TextFrame.java @@ -1,5 +1,65 @@ package org.eclipse.jetty.websocket.frames; -public class TextFrame { +/** + * Representation of a Text Data Frame (0x01). + */ +public class TextFrame extends BaseFrame +{ + private StringBuilder data = new StringBuilder(); + /** + * Default constructor (unspecified data) + */ + public TextFrame() + { + super(); + super.setOpcode(OP_TEXT); + } + + /** + * Copy Constructor + * + * @param base + * the base frame to work off of. + */ + public TextFrame(BaseFrame copy) + { + super(copy); + } + + /** + * Get the data + * + * @return the raw StringBuilder data (can be null) + */ + public StringBuilder getData() + { + return data; + } + + /** + * Set the data and payload length. + * + * @param str + * the String to set + */ + public void setData(String str) + { + int len = str.length(); + this.data = new StringBuilder(str); + this.setPayloadLength(len); + } + + /** + * Set the data and payload length. + * + * @param str + * the StringBuilder to set + */ + public void setData(StringBuilder str) + { + int len = str.length(); + this.data = str; + this.setPayloadLength(len); + } }