Refactoring out the contents of the .api.WebSocket class in prep for rethink of original API class
This commit is contained in:
parent
aaf27d7e2a
commit
5a529ad4a2
|
@ -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 <code>Sec-WebSocket-Accept</code> and <code>Sec-WebSocket-Accept</code> headers.
|
||||
* <p>
|
||||
* 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 <code>Sec-WebSocket-Accept</code> and <code>Sec-WebSocket-Key</code> http headers.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-1.3">Opening Handshake (Section 1.3)</a>
|
||||
*/
|
||||
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 <code>Sec-WebSocket-Accept</code> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package org.eclipse.jetty.websocket.api;
|
||||
|
||||
/**
|
||||
* The <a href="https://tools.ietf.org/html/rfc6455#section-7.4">RFC 6455 specified status codes</a>.
|
||||
*/
|
||||
public class StatusCode
|
||||
{
|
||||
/**
|
||||
* 1000 indicates a normal closure, meaning that the purpose for which the connection was established has been fulfilled.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
public final static short SHUTDOWN = 1001;
|
||||
/**
|
||||
* 1002 indicates that an endpoint is terminating the connection due to a protocol error.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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).
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
public final static short BAD_DATA = 1003;
|
||||
/**
|
||||
* Reserved. The specific meaning might be defined in the future.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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 [<a href="https://tools.ietf.org/html/rfc3629">RFC3629</a>] data within a text message).
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
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).
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
|
||||
*/
|
||||
public final static short FAILED_TLS_HANDSHAKE = 1015;
|
||||
}
|
|
@ -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 <a href="https://tools.ietf.org/html/rfc6455">RFC-6455</a>.
|
||||
|
@ -15,57 +10,4 @@ public class WebSocket
|
|||
* Per <a href="https://tools.ietf.org/html/rfc6455#section-1.3">RFC 6455, section 1.3</a> - Opening Handshake - this version is "13"
|
||||
*/
|
||||
public final static int VERSION = 13;
|
||||
|
||||
/**
|
||||
* Globally Unique Identifier for use in WebSocket handshake within <code>Sec-WebSocket-Accept</code> and <code>Sec-WebSocket-Key</code> http headers.
|
||||
* <p>
|
||||
* See <a href="https://tools.ietf.org/html/rfc6455#section-1.3">Opening Handshake (Section 1.3)</a>
|
||||
*/
|
||||
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 <code>Sec-WebSocket-Accept</code> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">Close Frame (0x08)</a>.
|
||||
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package org.eclipse.jetty.websocket.server;
|
||||
|
||||
public class WebSocketServletTest
|
||||
{
|
||||
|
||||
}
|
Loading…
Reference in New Issue