diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java
index e79c40b815..9e904ddd00 100644
--- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java
+++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java
@@ -15,13 +15,14 @@
*/
package org.jboss.netty.handler.codec.http.websocketx;
+import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.util.CharsetUtil;
/**
* Web Socket Frame for closing the connection
*/
public class CloseWebSocketFrame extends WebSocketFrame {
-
/**
* Creates a new empty close frame.
*/
@@ -29,6 +30,63 @@ public class CloseWebSocketFrame extends WebSocketFrame {
setBinaryData(ChannelBuffers.EMPTY_BUFFER);
}
+ /**
+ * Creates a new empty close frame with closing status code and reason text
+ *
+ * @param statusCode
+ * Integer status code as per RFC 6455. For
+ * example, 1000 indicates normal closure.
+ * @param reasonText
+ * Reason text. Set to null if no text.
+ */
+ public CloseWebSocketFrame(int statusCode, String reasonText) {
+ this(true, 0, statusCode, reasonText);
+ }
+
+ /**
+ * Creates a new close frame with no losing status code and no reason text
+ *
+ * @param finalFragment
+ * flag indicating if this frame is the final fragment
+ * @param rsv
+ * reserved bits used for protocol extensions
+ */
+ public CloseWebSocketFrame(boolean finalFragment, int rsv) {
+ this(finalFragment, rsv, null);
+ }
+
+ /**
+ * Creates a new close frame with closing status code and reason text
+ *
+ * @param finalFragment
+ * flag indicating if this frame is the final fragment
+ * @param rsv
+ * reserved bits used for protocol extensions
+ * @param statusCode
+ * Integer status code as per RFC 6455. For
+ * example, 1000 indicates normal closure.
+ * @param reasonText
+ * Reason text. Set to null if no text.
+ */
+ public CloseWebSocketFrame(boolean finalFragment, int rsv, int statusCode, String reasonText) {
+ setFinalFragment(finalFragment);
+ setRsv(rsv);
+
+ byte[] reasonBytes = new byte[0];
+ if (reasonText != null) {
+ reasonBytes = reasonText.getBytes(CharsetUtil.UTF_8);
+ }
+
+ ChannelBuffer binaryData = ChannelBuffers.buffer(2 + reasonBytes.length);
+ binaryData.writeShort(statusCode);
+ if (reasonBytes.length > 0) {
+ binaryData.writeBytes(reasonBytes);
+ }
+
+ binaryData.readerIndex(0);
+ setBinaryData(binaryData);
+ }
+
/**
* Creates a new close frame
*
@@ -36,10 +94,51 @@ public class CloseWebSocketFrame extends WebSocketFrame {
* flag indicating if this frame is the final fragment
* @param rsv
* reserved bits used for protocol extensions
+ * @param binaryData
+ * the content of the frame. Must be 2 byte integer followed by optional UTF-8 encoded string.
*/
- public CloseWebSocketFrame(boolean finalFragment, int rsv) {
+ public CloseWebSocketFrame(boolean finalFragment, int rsv, ChannelBuffer binaryData) {
setFinalFragment(finalFragment);
setRsv(rsv);
+ if (binaryData == null) {
+ setBinaryData(ChannelBuffers.EMPTY_BUFFER);
+ } else {
+ setBinaryData(binaryData);
+ }
+ }
+
+ /**
+ * Returns the closing status code as per RFC 6455. If
+ * a status code is set, -1 is returned.
+ */
+ public int getStatusCode() {
+ ChannelBuffer binaryData = this.getBinaryData();
+ if (binaryData == null || binaryData.capacity() == 0) {
+ return -1;
+ }
+
+ binaryData.readerIndex(0);
+ int statusCode = binaryData.readShort();
+ binaryData.readerIndex(0);
+
+ return statusCode;
+ }
+
+ /**
+ * Returns the reason text as per RFC 6455 If a reason
+ * text is not supplied, an empty string is returned.
+ */
+ public String getReasonText() {
+ ChannelBuffer binaryData = this.getBinaryData();
+ if (binaryData == null || binaryData.capacity() <= 2) {
+ return "";
+ }
+
+ binaryData.readerIndex(2);
+ String reasonText = binaryData.toString(CharsetUtil.UTF_8);
+ binaryData.readerIndex(0);
+
+ return reasonText;
}
@Override
diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java
index 9d2cf1b2dc..cd9cf5c9d7 100644
--- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java
+++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java
@@ -284,8 +284,9 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder= 0 && statusCode <= 999) || (statusCode >= 1004 && statusCode <= 1006)
+ || (statusCode >= 1012 && statusCode <= 2999)) {
+ protocolViolation(channel, "Invalid close frame status code: " + statusCode);
+ }
+
+ // May have UTF-8 message
+ if (buffer.readableBytes() > 0) {
+ byte[] b = new byte[buffer.readableBytes()];
+ buffer.readBytes(b);
+ try {
+ new UTF8Output(b);
+ } catch (UTF8Exception ex) {
+ protocolViolation(channel, "Invalid close frame reason text. Invalid UTF-8 bytes");
+ }
+ }
+
+ // Restore reader index
+ buffer.readerIndex(idx);
+ }
}