diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/AcceptHash.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/AcceptHash.java
new file mode 100644
index 00000000000..7d15be172ec
--- /dev/null
+++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/AcceptHash.java
@@ -0,0 +1,56 @@
+package org.eclipse.jetty.websocket.api;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+
+import org.eclipse.jetty.util.B64Code;
+import org.eclipse.jetty.util.StringUtil;
+
+/**
+ * Logic for working with the Sec-WebSocket-Accept
and Sec-WebSocket-Accept
headers.
+ *
+ * This is kept separate from Connection objects to facilitate difference in behavior between client and server, as well as making testing easier.
+ */
+public class AcceptHash
+{
+ /**
+ * Globally Unique Identifier for use in WebSocket handshake within Sec-WebSocket-Accept
and Sec-WebSocket-Key
http headers.
+ *
+ * See Opening Handshake (Section 1.3)
+ */
+ private final static byte[] MAGIC;
+
+ static
+ {
+ try
+ {
+ MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".getBytes(StringUtil.__ISO_8859_1);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Concatenate the provided key with the Magic GUID and return the Base64 encoded form.
+ *
+ * @param key
+ * the key to hash
+ * @return the Sec-WebSocket-Accept
header response (per opening handshake spec)
+ */
+ public static String hashKey(String key)
+ {
+ try
+ {
+ MessageDigest md = MessageDigest.getInstance("SHA1");
+ md.update(key.getBytes("UTF-8"));
+ md.update(MAGIC);
+ return new String(B64Code.encode(md.digest()));
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/PolicyViolationException.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/PolicyViolationException.java
index 37540a0d2a1..1c0f50a7c99 100644
--- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/PolicyViolationException.java
+++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/PolicyViolationException.java
@@ -5,16 +5,16 @@ public class PolicyViolationException extends CloseException
{
public PolicyViolationException(String message)
{
- super(WebSocket.CLOSE_POLICY_VIOLATION,message);
+ super(StatusCode.POLICY_VIOLATION,message);
}
public PolicyViolationException(String message, Throwable t)
{
- super(WebSocket.CLOSE_POLICY_VIOLATION,message,t);
+ super(StatusCode.POLICY_VIOLATION,message,t);
}
public PolicyViolationException(Throwable t)
{
- super(WebSocket.CLOSE_POLICY_VIOLATION,t);
+ super(StatusCode.POLICY_VIOLATION,t);
}
}
diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/StatusCode.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/StatusCode.java
new file mode 100644
index 00000000000..78e3559e326
--- /dev/null
+++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/StatusCode.java
@@ -0,0 +1,95 @@
+package org.eclipse.jetty.websocket.api;
+
+/**
+ * The RFC 6455 specified status codes.
+ */
+public class StatusCode
+{
+ /**
+ * 1000 indicates a normal closure, meaning that the purpose for which the connection was established has been fulfilled.
+ *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short NORMAL = 1000; + /** + * 1001 indicates that an endpoint is "going away", such as a server going down or a browser having navigated away from a page. + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short SHUTDOWN = 1001; + /** + * 1002 indicates that an endpoint is terminating the connection due to a protocol error. + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short PROTOCOL = 1002; + /** + * 1003 indicates that an endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands + * only text data MAY send this if it receives a binary message). + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short BAD_DATA = 1003; + /** + * Reserved. The specific meaning might be defined in the future. + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short UNDEFINED = 1004; + /** + * 1005 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting + * a status code to indicate that no status code was actually present. + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short NO_CODE = 1005; + /** + * 1006 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting + * a status code to indicate that the connection was closed abnormally, e.g., without sending or receiving a Close control frame. + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short NO_CLOSE = 1006; + /** + * 1007 indicates that an endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the + * message (e.g., non-UTF-8 [RFC3629] data within a text message). + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short BAD_PAYLOAD = 1007; + /** + * 1008 indicates that an endpoint is terminating the connection because it has received a message that violates its policy. This is a generic status code + * that can be returned when there is no other more suitable status code (e.g., 1003 or 1009) or if there is a need to hide specific details about the + * policy. + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short POLICY_VIOLATION = 1008; + /** + * 1009 indicates that an endpoint is terminating the connection because it has received a message that is too big for it to process. + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short MESSAGE_TOO_LARGE = 1009; + /** + * 1010 indicates that an endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the + * server didn't return them in the response message of the WebSocket handshake. The list of extensions that are needed SHOULD appear in the /reason/ part + * of the Close frame. Note that this status code is not used by the server, because it can fail the WebSocket handshake instead. + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short REQUIRED_EXTENSION = 1010; + /** + * 1011 indicates that a server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request. + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes. + */ + public final static short SERVER_ERROR = 1011; + /** + * 1015 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting + * a status code to indicate that the connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified). + *
+ * See RFC 6455, Section 7.4.1 Defined Status Codes.
+ */
+ public final static short FAILED_TLS_HANDSHAKE = 1015;
+}
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 68938e71fd7..c83a9ed22c9 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
@@ -1,10 +1,5 @@
package org.eclipse.jetty.websocket.api;
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-
-import org.eclipse.jetty.util.B64Code;
-import org.eclipse.jetty.util.StringUtil;
/**
* Constants for WebSocket protocol as-defined in RFC-6455.
@@ -15,57 +10,4 @@ public class WebSocket
* Per RFC 6455, section 1.3 - Opening Handshake - this version is "13"
*/
public final static int VERSION = 13;
-
- /**
- * Globally Unique Identifier for use in WebSocket handshake within Sec-WebSocket-Accept
and Sec-WebSocket-Key
http headers.
- *
- * See Opening Handshake (Section 1.3)
- */
- private final static byte[] MAGIC;
-
- 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
- {
- try
- {
- MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".getBytes(StringUtil.__ISO_8859_1);
- }
- catch (UnsupportedEncodingException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Concatenate the provided key with the Magic GUID and return the Base64 encoded form.
- * @param key the key to hash
- * @return the Sec-WebSocket-Accept
header response (per opening handshake spec)
- */
- public static String hashKey(String key)
- {
- try
- {
- MessageDigest md = MessageDigest.getInstance("SHA1");
- md.update(key.getBytes("UTF-8"));
- md.update(MAGIC);
- return new String(B64Code.encode(md.digest()));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
- }
}
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 acaa1a98401..0a8d079e0a5 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,7 +1,7 @@
package org.eclipse.jetty.websocket.frames;
import org.eclipse.jetty.websocket.api.OpCode;
-import org.eclipse.jetty.websocket.api.WebSocket;
+import org.eclipse.jetty.websocket.api.StatusCode;
/**
* Representation of a Close Frame (0x08).
@@ -13,7 +13,7 @@ public class CloseFrame extends ControlFrame
public CloseFrame()
{
- this(WebSocket.CLOSE_NORMAL); // TODO: evaluate default (or unspecified status code)
+ this(StatusCode.NORMAL); // TODO: evaluate default (or unspecified status code)
}
public CloseFrame(short statusCode)
diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/ClosePayloadParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/ClosePayloadParserTest.java
index 37e0e701ee8..d71861cbc87 100644
--- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/ClosePayloadParserTest.java
+++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/ClosePayloadParserTest.java
@@ -6,7 +6,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.Debug;
-import org.eclipse.jetty.websocket.api.WebSocket;
+import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.CloseFrame;
@@ -24,7 +24,7 @@ public class ClosePayloadParserTest
byte utf[] = expectedReason.getBytes(StringUtil.__UTF8_CHARSET);
ByteBuffer payload = ByteBuffer.allocate(utf.length + 2);
- payload.putShort(WebSocket.CLOSE_NORMAL);
+ payload.putShort(StatusCode.NORMAL);
payload.put(utf,0,utf.length);
payload.flip();
@@ -44,7 +44,7 @@ public class ClosePayloadParserTest
capture.assertNoErrors();
capture.assertHasFrame(CloseFrame.class,1);
CloseFrame txt = (CloseFrame)capture.getFrames().get(0);
- Assert.assertThat("CloseFrame.statusCode",txt.getStatusCode(),is(WebSocket.CLOSE_NORMAL));
+ Assert.assertThat("CloseFrame.statusCode",txt.getStatusCode(),is(StatusCode.NORMAL));
Assert.assertThat("CloseFrame.data",txt.getReason(),is(expectedReason));
}
}
diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/TextPayloadParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/TextPayloadParserTest.java
index 3cbe159efdb..5f12af567e1 100644
--- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/TextPayloadParserTest.java
+++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/TextPayloadParserTest.java
@@ -7,7 +7,7 @@ import java.util.Arrays;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.PolicyViolationException;
-import org.eclipse.jetty.websocket.api.WebSocket;
+import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.frames.TextFrame;
@@ -43,7 +43,7 @@ public class TextPayloadParserTest
capture.assertHasNoFrames();
PolicyViolationException err = (PolicyViolationException)capture.getErrors().get(0);
- Assert.assertThat("Error.closeCode",err.getCloseCode(),is(WebSocket.CLOSE_POLICY_VIOLATION));
+ Assert.assertThat("Error.closeCode",err.getCloseCode(),is(StatusCode.POLICY_VIOLATION));
}
@Test
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketMessageRFC6455Test.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketMessageRFC6455Test.java
index 15f78bea5da..849673c8a38 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketMessageRFC6455Test.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketMessageRFC6455Test.java
@@ -40,7 +40,9 @@ import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.websocket.WebSocket;
+import org.eclipse.jetty.websocket.api.AcceptHash;
import org.eclipse.jetty.websocket.api.OpCode;
+import org.eclipse.jetty.websocket.api.StatusCode;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
@@ -929,7 +931,7 @@ public class WebSocketMessageRFC6455Test
@Test
public void testHash()
{
- assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",org.eclipse.jetty.websocket.api.WebSocket.hashKey("dGhlIHNhbXBsZSBub25jZQ=="));
+ assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",AcceptHash.hashKey("dGhlIHNhbXBsZSBub25jZQ=="));
}
@Test
@@ -1096,7 +1098,7 @@ public class WebSocketMessageRFC6455Test
assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read());
assertEquals(19,input.read());
int code=((0xff&input.read())*0x100)+(0xff&input.read());
- assertEquals(org.eclipse.jetty.websocket.api.WebSocket.CLOSE_MESSAGE_TOO_LARGE,code);
+ assertEquals(StatusCode.MESSAGE_TOO_LARGE,code);
lookFor("Message size > 15",input);
}
@@ -1146,7 +1148,7 @@ public class WebSocketMessageRFC6455Test
assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read());
assertEquals(19,input.read());
int code=((0xff&input.read())*0x100)+(0xff&input.read());
- assertEquals(org.eclipse.jetty.websocket.api.WebSocket.CLOSE_MESSAGE_TOO_LARGE,code);
+ assertEquals(StatusCode.MESSAGE_TOO_LARGE,code);
lookFor("Message size > 15",input);
}
@@ -1210,7 +1212,7 @@ public class WebSocketMessageRFC6455Test
assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read());
assertEquals(30,input.read());
int code=((0xff&input.read())*0x100)+(0xff&input.read());
- assertEquals(org.eclipse.jetty.websocket.api.WebSocket.CLOSE_MESSAGE_TOO_LARGE,code);
+ assertEquals(StatusCode.MESSAGE_TOO_LARGE,code);
lookFor("Text message size > 15 chars",input);
}
@@ -1264,7 +1266,7 @@ public class WebSocketMessageRFC6455Test
assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read());
assertEquals(30,input.read());
int code=((0xff&input.read())*0x100)+(0xff&input.read());
- assertEquals(org.eclipse.jetty.websocket.api.WebSocket.CLOSE_MESSAGE_TOO_LARGE,code);
+ assertEquals(StatusCode.MESSAGE_TOO_LARGE,code);
lookFor("Text message size > 15 chars",input);
}
@@ -1319,7 +1321,7 @@ public class WebSocketMessageRFC6455Test
assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read());
assertEquals(33,input.read());
int code=((0xff&input.read())*0x100)+(0xff&input.read());
- assertEquals(org.eclipse.jetty.websocket.api.WebSocket.CLOSE_MESSAGE_TOO_LARGE,code);
+ assertEquals(StatusCode.MESSAGE_TOO_LARGE,code);
lookFor("Text message size > 10240 chars",input);
}
@@ -1366,7 +1368,7 @@ public class WebSocketMessageRFC6455Test
assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read());
assertEquals(15,input.read());
int code=((0xff&input.read())*0x100)+(0xff&input.read());
- assertEquals(org.eclipse.jetty.websocket.api.WebSocket.CLOSE_BAD_PAYLOAD,code);
+ assertEquals(StatusCode.BAD_PAYLOAD,code);
lookFor("Invalid UTF-8",input);
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletTest.java
new file mode 100644
index 00000000000..793c6f6fd6c
--- /dev/null
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletTest.java
@@ -0,0 +1,6 @@
+package org.eclipse.jetty.websocket.server;
+
+public class WebSocketServletTest
+{
+
+}