diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketGenerator.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketGenerator.java deleted file mode 100644 index a2759ddec21..00000000000 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketGenerator.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Intalio, Inc. - * ====================================================================== - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * The Apache License v2.0 is available at - * http://www.opensource.org/licenses/apache2.0.php - * - * You may elect to redistribute this code under either of these licenses. - *******************************************************************************/ -// ======================================================================== -// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== - -package org.eclipse.jetty.websocket; - -import java.io.IOException; - - - -/* ------------------------------------------------------------ */ -/** WebSocketGenerator. - */ -public interface WebSocketGenerator -{ - int flush() throws IOException; - boolean isBufferEmpty(); - void addFrame(byte flags,byte opcode, byte[] content, int offset, int length) throws IOException; -} 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 deleted file mode 100644 index fdf10ea280f..00000000000 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorRFC6455.java +++ /dev/null @@ -1,275 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Intalio, Inc. - * ====================================================================== - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * The Apache License v2.0 is available at - * http://www.opensource.org/licenses/apache2.0.php - * - * You may elect to redistribute this code under either of these licenses. - *******************************************************************************/ -// ======================================================================== -// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== - -package org.eclipse.jetty.websocket; - -import java.nio.ByteBuffer; - -import org.eclipse.jetty.websocket.generator.Generator; - - -/* ------------------------------------------------------------ */ -/** WebSocketGenerator. - * This class generates websocket packets. - * It is fully synchronized because it is likely that async - * threads will call the addMessage methods while other - * threads are flushing the generator. - * @deprecated see {@link Generator} replacement - */ -@Deprecated -public class WebSocketGeneratorRFC6455 /* implements WebSocketGenerator */ -{ - // final private WebSocketBuffers _buffers; - // final private EndPoint _endp; - private ByteBuffer _buffer; - // private final byte[] _mask=new byte[4]; - private int _m; - private boolean _opsent; - // private final MaskGen _maskGen; - private boolean _closed; - - /* TODO: Migrate to new Jetty9 IO - public WebSocketGeneratorRFC6455(WebSocketBuffers buffers, EndPoint endp) - { - _buffers=buffers; - _endp=endp; - _maskGen=null; - } - - public WebSocketGeneratorRFC6455(WebSocketBuffers buffers, EndPoint endp, MaskGen maskGen) - { - _buffers=buffers; - _endp=endp; - _maskGen=maskGen; - } - */ - - public synchronized ByteBuffer getBuffer() - { - return _buffer; - } - - /* TODO: Migrate to new Jetty9 IO - public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException - { - // System.err.printf("<< %s %s %s\n",TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),length); - - if (_closed) - throw new EofException("Closed"); - if (opcode==WebSocketConnectionRFC6455.OP_CLOSE) - _closed=true; - - boolean mask=_maskGen!=null; - - if (_buffer==null) - _buffer=mask?_buffers.getData():_buffers.getDirectBuffer(); - - boolean last=WebSocketConnectionRFC6455.isLastFrame(flags); - - int space=mask?14:10; - - do - { - opcode = _opsent?WebSocketConnectionRFC6455.OP_CONTINUATION:opcode; - opcode=(byte)(((0xf&flags)<<4)+(0xf&opcode)); - _opsent=true; - - int payload=length; - if (payload+space>_buffer.capacity()) - { - // We must fragement, so clear FIN bit - opcode=(byte)(opcode&0x7F); // Clear the FIN bit - payload=_buffer.capacity()-space; - } - else if (last) - opcode= (byte)(opcode|0x80); // Set the FIN bit - - // ensure there is space for header - if (_buffer.space() <= space) - { - flushBuffer(); - if (_buffer.space() <= space) - flush(); - } - - // write the opcode and length - if (payload>0xffff) - { - _buffer.put(new byte[]{ - opcode, - mask?(byte)0xff:(byte)0x7f, - (byte)0, - (byte)0, - (byte)0, - (byte)0, - (byte)((payload>>24)&0xff), - (byte)((payload>>16)&0xff), - (byte)((payload>>8)&0xff), - (byte)(payload&0xff)}); - } - else if (payload >=0x7e) - { - _buffer.put(new byte[]{ - opcode, - mask?(byte)0xfe:(byte)0x7e, - (byte)(payload>>8), - (byte)(payload&0xff)}); - } - else - { - _buffer.put(new byte[]{ - opcode, - (byte)(mask?(0x80|payload):payload)}); - } - - // write mask - if (mask) - { - _maskGen.genMask(_mask); - _m=0; - _buffer.put(_mask); - } - - // write payload - int remaining = payload; - while (remaining > 0) - { - _buffer.compact(); - int chunk = remaining < _buffer.space() ? remaining : _buffer.space(); - - if (mask) - { - for (int i=0;i 0) - { - // Gently flush the data, issuing a non-blocking write - flushBuffer(); - } - else - { - // Forcibly flush the data, issuing a blocking write - flush(); - if (remaining == 0) - { - // Gently flush the data, issuing a non-blocking write - flushBuffer(); - } - } - } - offset+=payload; - length-=payload; - } - while (length>0); - _opsent=!last; - - if (_buffer!=null && _buffer.length()==0) - { - _buffers.returnBuffer(_buffer); - _buffer=null; - } - } - - public synchronized int flushBuffer() throws IOException - { - if (!_endp.isOpen()) - throw new EofException(); - - if (_buffer!=null) - { - int flushed=_buffer.hasContent()?_endp.flush(_buffer):0; - if (_closed&&_buffer.length()==0) - _endp.shutdownOutput(); - return flushed; - } - - return 0; - } - - public synchronized int flush() throws IOException - { - if (_buffer==null) - return 0; - int result = flushBuffer(); - - if (!_endp.isBlocking()) - { - long now = System.currentTimeMillis(); - long end=now+_endp.getMaxIdleTime(); - while (_buffer.length()>0) - { - boolean ready = _endp.blockWritable(end-now); - if (!ready) - { - now = System.currentTimeMillis(); - if (now + * Acceptable method patterns.
+ * Note: methodName can be any name you want to use. + *
    + *
  1. public void methodName(byte payload[], int offset, int length)
  2. + *
  3. public void methodName({@link ByteBuffer} payload)
  4. + *
  5. public void methodName({@link WebSocketConnection} conn, byte payload[], int offset, int length)
  6. + *
  7. public void methodName({@link WebSocketConnection} conn, {@link ByteBuffer} payload)
  8. + *
+ */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(value = +{ ElementType.METHOD }) +public @interface OnWebSocketBinary +{ + /* no config */ +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketClose.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketClose.java new file mode 100644 index 00000000000..65cae6b8494 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketClose.java @@ -0,0 +1,28 @@ +package org.eclipse.jetty.websocket.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.eclipse.jetty.websocket.api.WebSocketConnection; + +/** + * Annotation for tagging methods to receive connection close events. + *

+ * Acceptable method patterns.
+ * Note: methodName can be any name you want to use. + *

    + *
  1. public void methodName(int statusCode, String reason)
  2. + *
  3. public void methodName({@link WebSocketConnection} conn, int statusCode, String reason)
  4. + *
+ */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(value = +{ ElementType.METHOD }) +public @interface OnWebSocketClose +{ + /* no config */ +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketConnect.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketConnect.java new file mode 100644 index 00000000000..e440baa73b9 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketConnect.java @@ -0,0 +1,27 @@ +package org.eclipse.jetty.websocket.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.eclipse.jetty.websocket.api.WebSocketConnection; + +/** + * Annotation for tagging methods to receive connection open events. + *

+ * Only 1 acceptable method pattern for this annotation.
+ * Note: methodName can be any name you want to use. + *

    + *
  1. public void methodName({@link WebSocketConnection} conn)
  2. + *
+ */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(value = +{ ElementType.METHOD }) +public @interface OnWebSocketConnect +{ + /* no config */ +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketFrame.java new file mode 100644 index 00000000000..e6b9c816cbe --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketFrame.java @@ -0,0 +1,45 @@ +package org.eclipse.jetty.websocket.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.eclipse.jetty.websocket.api.WebSocketConnection; +import org.eclipse.jetty.websocket.frames.BaseFrame; + +/** + * (ADVANCED) Annotation for tagging methods to receive frame events. + *

+ * Note: any frame derived from {@link BaseFrame} is acceptable to use as the last parameter here. + *

+ * Acceptable method patterns.
+ * Note: methodName can be any name you want to use. + *

    + *
  1. public void methodName({@link BaseFrame} frame)
  2. + *
  3. public void methodName(BinaryFrame frame)
  4. + *
  5. public void methodName(CloseFrame frame)
  6. + *
  7. public void methodName(ControlFrame frame)
  8. + *
  9. public void methodName(DataFrame frame)
  10. + *
  11. public void methodName(PingFrame frame)
  12. + *
  13. public void methodName(PongFrame frame)
  14. + *
  15. public void methodName(TextFrame frame)
  16. + *
  17. public void methodName({@link WebSocketConnection} conn, {@link BaseFrame} frame)
  18. + *
  19. public void methodName({@link WebSocketConnection} conn, BinaryFrame frame)
  20. + *
  21. public void methodName({@link WebSocketConnection} conn, CloseFrame frame)
  22. + *
  23. public void methodName({@link WebSocketConnection} conn, ControlFrame frame)
  24. + *
  25. public void methodName({@link WebSocketConnection} conn, DataFrame frame)
  26. + *
  27. public void methodName({@link WebSocketConnection} conn, PingFrame frame)
  28. + *
  29. public void methodName({@link WebSocketConnection} conn, PongFrame frame)
  30. + *
  31. public void methodName({@link WebSocketConnection} conn, TextFrame frame)
  32. + *
+ */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(value = +{ ElementType.METHOD }) +public @interface OnWebSocketFrame +{ + /* no config */ +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketText.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketText.java new file mode 100644 index 00000000000..bebeaa3171e --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/OnWebSocketText.java @@ -0,0 +1,28 @@ +package org.eclipse.jetty.websocket.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.eclipse.jetty.websocket.api.WebSocketConnection; + +/** + * Annotation for tagging methods to receive Text message events. + *

+ * Acceptable method patterns.
+ * Note: methodName can be any name you want to use. + *

    + *
  1. public void methodName(String text)
  2. + *
  3. public void methodName({@link WebSocketConnection} conn, String text)
  4. + *
+ */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(value = +{ ElementType.METHOD }) +public @interface OnWebSocketText +{ + /* no config */ +} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/WebSocket.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/WebSocket.java new file mode 100644 index 00000000000..9bdf852f335 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/annotations/WebSocket.java @@ -0,0 +1,23 @@ +package org.eclipse.jetty.websocket.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Tags a POJO as being a WebSocket class. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(value = +{ ElementType.TYPE }) +public @interface WebSocket +{ + int maxBinarySize() default 8192; + + int maxBufferSize() default 8192; + + int maxTextSize() default 8192; +} 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 deleted file mode 100644 index 148960aa687..00000000000 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocket.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.eclipse.jetty.websocket.api; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import org.eclipse.jetty.util.Callback; -import org.eclipse.jetty.websocket.frames.BaseFrame; -import org.eclipse.jetty.websocket.frames.BinaryFrame; -import org.eclipse.jetty.websocket.frames.TextFrame; - -/** - * Constants for WebSocket protocol as-defined in RFC-6455. - *

- * NOTE: Proposed interface for API (not yet settled) - */ -public interface WebSocket -{ - /** - * Advanced usage, for those interested in flags - */ - public static interface BinaryFrameListener - { - void onWebSocketBinary(BinaryFrame frame); - } - - /** - * Basic usage. - */ - public static interface BinaryListener - { - void onWebSocketBinary(byte buf[], int offset, int len); - } - - /** - * NIO flavored basic usage. - */ - public static interface ByteBufferListener - { - void onWebSocketBinary(ByteBuffer... buffer); - } - - public static interface Connection - { - /** - * Terminate connection, normally, without a reason. - *

- * Issues a CloseFrame via {@link #write(Object, Callback, BaseFrame...)} - * - * @TODO: determine contract for dealing with pending incoming frames. - */ - void close(); - - /** - * Terminate connection, with status code. - *

- * Issues a CloseFrame via {@link #write(Object, Callback, BaseFrame...)} - * - * @param statusCode - * the status code - * @param reason - * the (optional) reason. (can be null for no reason) - * @TODO: determine contract for dealing with pending incoming frames. - */ - void close(int statusCode, String reason); - - String getSubProtocol(); - - boolean isOpen(); - - /** - * Basic usage, results in non-blocking call to {@link #write(Object, Callback, ByteBuffer...)} - */ - void sendBinary(byte[] data, int offset, int length) throws IOException; - - /** - * Basic usage, results in non-blocking call to {@link #write(Object, Callback, ByteBuffer...)} - */ - void sendBinary(ByteBuffer buffer) throws IOException; - - /** - * Basic usage, results in non-blocking call to {@link #write(Object, Callback, ByteBuffer...)} - */ - void sendBinary(ByteBuffer... buffers) throws IOException; - - /** - * Basic usage, results in non-blocking call to {@link #write(Object, Callback, String...)} - */ - void sendText(String message) throws IOException; - - /** - * Advanced usage, with callbacks, enters into outgoing queue - */ - void write(C context, Callback callback, BaseFrame... frames) throws IOException; - - /** - * Advanced usage, with callbacks, enters into outgoing queue - */ - void write(C context, Callback callback, ByteBuffer... buffers) throws IOException; - - /** - * Advanced usage, with callbacks, enters into outgoing queue - */ - void write(C context, Callback callback, String... messages) throws IOException; - } - - /** - * Advanced usage, text frame access to flags as well - */ - public static interface TextFrameListener - { - void onWebSocketTextFrame(TextFrame frame); - } - - /** - * Basic usage - */ - public static interface TextListener - { - void onWebSocketText(String message); - } - - /** - * Per RFC 6455, section 1.3 - Opening Handshake - this version is "13" - */ - public final static int VERSION = 13; - - void onClose(int statusCode, String reason); - - void onConnect(WebSocket.Connection connection); - - /** - * Annotation Ideas (Various WebSocket Events): - * - *

-     * @OnWebSocketHandshake (server side only?)
-     * public void {methodname}(WebSocket.Connection conn)
-     * 
-     * @OnWebSocketConnect
-     * public void {methodname}(WebSocket.Connection conn)
-     * 
-     * @OnWebSocketDisconnect
-     * public void {methodname}(WebSocket.Connection conn)
-     * 
-     * @OnWebSocketFrame(type=CloseFrame.class)
-     * public void {methodname}(CloseFrame frame);
-     * public void {methodname}(WebSocket.Connection conn, CloseFrame frame);
-     * 
-     * @OnWebSocketText
-     * public void {methodname}(String text);
-     * public void {methodname}(WebSocket.Connection conn, String text);
-     * 
-     * @OnWebSocketBinary
-     * public void {methodname}(byte buf[], int offset, int length);
-     * public void {methodname}(WebSocket.Connection conn, byte buf[], int offset, int length);
-     * public void {methodname}(ByteBuffer buffer);
-     * public void {methodname}(WebSocket.Connection conn, ByteBuffer buffer);
-     * 
-     * @OnWebSocketClose
-     * public void {methodnamne}(int statusCode, String reason);
-     * public void {methodnamne}(WebSocket.Connection conn, int statusCode, String reason);
-     * 
- */ -} diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnection.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnection.java new file mode 100644 index 00000000000..36ad4003af2 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnection.java @@ -0,0 +1,104 @@ +package org.eclipse.jetty.websocket.api; + +import java.io.IOException; +import java.net.InetAddress; +import java.nio.ByteBuffer; + +import org.eclipse.jetty.util.Callback; + +/** + * Connection interface for WebSocket protocol RFC-6455. + */ +public interface WebSocketConnection +{ + /** + * Terminate connection, {@link StatusCode#NORMAL}, without a reason. + *

+ * Basic usage: results in an non-blocking async write, then connection close. + */ + void close(); + + /** + * Terminate connection, with status code. + *

+ * Advanced usage: results in an non-blocking async write, then connection close. + * + * @param statusCode + * the status code + * @param reason + * the (optional) reason. (can be null for no reason) + * @see StatusCode + */ + void close(int statusCode, String reason); + + /** + * Access the (now read-only) {@link WebSocketPolicy} in use for this connection. + * + * @return the policy in use + */ + WebSocketPolicy getPolicy(); + + /** + * Get the remote Address in use for this connection. + * + * @return the remote address if available. (situations like mux extension and proxying makes this information unreliable) + */ + InetAddress getRemoteAddress(); + + /** + * Get the SubProtocol in use for this connection. + * + * @return the negotiated sub protocol name in use for this connection. + */ + String getSubProtocol(); + + /** + * Simple test to see if connection is open (and not closed) + * + * @return true if connection still open + */ + boolean isOpen(); + + /** + * Send a binary message. + *

+ * Basic usage, results in an non-blocking async write. + */ + void write(byte[] data, int offset, int length) throws IOException; + + /** + * Send a series of binary messages. + *

+ * Note: each buffer results in its own binary message frame. + *

+ * Basic usage, results in a series of non-blocking async writes. + */ + void write(ByteBuffer... buffers) throws IOException; + + /** + * Send a series of binary messages. + *

+ * Note: each buffer results in its own binary message frame. + *

+ * Advanced usage, with callbacks, allows for concurrent NIO style results of the entire write operation. (Callback is only called once at the end of + * processing all of the buffers) + */ + void write(C context, Callback callback, ByteBuffer... buffers) throws IOException; + + /** + * Send a series of text messages. + *

+ * Note: each messages results in its own text message frame. + *

+ * Advanced usage, with callbacks, allows for concurrent NIO style results of the entire write operation. (Callback is only called once at the end of + * processing all of the buffers) + */ + void write(C context, Callback callback, String... messages) throws IOException; + + /** + * Send a text message. + *

+ * Basic usage, results in an non-blocking async write. + */ + void write(String message) throws IOException; +} \ No newline at end of file diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java new file mode 100644 index 00000000000..befb3d61708 --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java @@ -0,0 +1,60 @@ +package org.eclipse.jetty.websocket.api; + +/** + * Basic WebSocket Listener interface for incoming WebSocket events. + */ +public interface WebSocketListener +{ + /** + * A WebSocket binary frame has been received. + * + * @param payload the raw payload array received + * @param offset the offset in the payload array where the data starts + * @param len the length of bytes in the payload + */ + void onWebSocketBinary(byte payload[], int offset, int len); + + /** + * A Close Event was received. + *

+ * The underlying {@link WebSocketConnection} will be considered closed at this point. + * + * @param statusCode + * the close status code. (See {@link StatusCode}) + * @param reason + * the optional reason for the close. + */ + void onWebSocketClose(int statusCode, String reason); + + /** + * A WebSocketConnection has connected successfully and is ready to be used. + *

+ * Note: It is a good idea to track this connection as a field in your object so that you can write messages back. + * + * @param connection + * the connection to use to send messages on. + */ + void onWebSocketConnect(WebSocketConnection connection); + + /** + * A WebSocket exception has occurred. + *

+ * Usually this occurs from bad / malformed incoming packets. (example: bad UTF8 data, frames that are too big, violations of the spec) + *

+ * This will result in the {@link WebSocketConnection} being closed by the implementing side. + *

+ * Note: you will receive no {@link #onWebSocketClose(int, String)} as this condition results in the API calling + * {@link WebSocketConnection#close(int, String)} for you. + * + * @param error + * the error that occurred. + */ + void onWebSocketException(WebSocketException error); + + /** + * A WebSocket Text frame was received. + * + * @param message + */ + void onWebSocketText(String message); +} diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1_1.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1_1.java index 731a89dc71b..d7223b4bcaf 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1_1.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1_1.java @@ -1,113 +1,304 @@ package org.eclipse.jetty.websocket.ab; - -import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.*; import java.nio.ByteBuffer; -import org.eclipse.jetty.io.StandardByteBufferPool; import org.eclipse.jetty.websocket.ByteBufferAssert; -import org.eclipse.jetty.websocket.Debug; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.frames.TextFrame; 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.parser.TextPayloadParser; import org.junit.Assert; import org.junit.Test; +/** + * Text Message Spec testing the {@link Generator} and {@link Parser} + */ public class ABCase1_1 { - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + private WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); + + @Test + public void testGenerate125ByteTextCase1_1_2() + { + int length = 125; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + textFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(length + 16); + generator.generate(actual,textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= length & 0x7F; + expected.put(b); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testGenerate126ByteTextCase1_1_3() + { + int length = 126; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + textFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(length + 16); + generator.generate(actual,textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + + // expected.put((byte)((length>>8) & 0xFF)); + // expected.put((byte)(length & 0xFF)); + expected.putShort((short)length); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testGenerate127ByteTextCase1_1_4() + { + int length = 127; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + textFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(length + 16); + generator.generate(actual,textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + + // expected.put((byte)((length>>8) & 0xFF)); + // expected.put((byte)(length & 0xFF)); + expected.putShort((short)length); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testGenerate128ByteTextCase1_1_5() + { + int length = 128; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + textFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(length + 16); + generator.generate(actual,textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + + expected.put((byte)(length >> 8)); + expected.put((byte)(length & 0xFF)); + // expected.putShort((short)length); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testGenerate65535ByteTextCase1_1_6() + { + int length = 65535; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + textFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(length + 16); + generator.generate(actual,textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + expected.put(new byte[] + { (byte)0xff, (byte)0xff }); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testGenerate65536ByteTextCase1_1_7() + { + int length = 65536; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + TextFrame textFrame = new TextFrame(builder.toString()); + textFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(length + 16); + generator.generate(actual,textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 11); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= 0x7F; + expected.put(b); + expected.put(new byte[] + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } @Test public void testGenerateEmptyTextCase1_1_1() { TextFrame textFrame = new TextFrame(""); textFrame.setFin(true); - + Generator generator = new Generator(policy); ByteBuffer actual = ByteBuffer.allocate(10); - generator.generate(actual, textFrame); + generator.generate(actual,textFrame); ByteBuffer expected = ByteBuffer.allocate(5); expected.put(new byte[] { (byte)0x81, (byte)0x00 }); - + actual.flip(); expected.flip(); - + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); } - - @Test - public void testParseEmptyTextCase1_1_1() - { - - ByteBuffer expected = ByteBuffer.allocate(5); - expected.put(new byte[] - { (byte)0x81, (byte)0x00 }); - - expected.flip(); - - Parser parser = new Parser(policy); - FrameParseCapture capture = new FrameParseCapture(); - parser.addListener(capture); - parser.parse(expected); - - capture.assertNoErrors(); - capture.assertHasFrame(TextFrame.class,1); - - TextFrame pActual = (TextFrame)capture.getFrames().get(0); - Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(0)); - ByteBufferAssert.assertSize("TextFrame.payload",0,pActual.getPayload()); - } - - @Test - public void testGenerate125ByteTextCase1_1_2() - { - int length = 125; - - StringBuilder builder = new StringBuilder(); - - for ( int i = 0 ; i < length ; ++i) - { - builder.append("*"); - } - - TextFrame textFrame = new TextFrame(builder.toString()); - textFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(length+16); - generator.generate(actual, textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= length & 0x7F; - expected.put(b); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse125ByteTextCase1_1_2() { @@ -120,71 +311,27 @@ public class ABCase1_1 byte b = 0x00; // no masking b |= length & 0x7F; expected.put(b); - - for ( int i = 0 ; i < length ; ++i ) + + for (int i = 0; i < length; ++i) { expected.put("*".getBytes()); } - + expected.flip(); - + Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(TextFrame.class,1); - + TextFrame pActual = (TextFrame)capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); } - - @Test - public void testGenerate126ByteTextCase1_1_3() - { - int length = 126; - - StringBuilder builder = new StringBuilder(); - - for ( int i = 0 ; i < length ; ++i) - { - builder.append("*"); - } - - TextFrame textFrame = new TextFrame(builder.toString()); - textFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(length+16); - generator.generate(actual, textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - - //expected.put((byte)((length>>8) & 0xFF)); - //expected.put((byte)(length & 0xFF)); - expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse126ByteTextCase1_1_3() { @@ -199,70 +346,26 @@ public class ABCase1_1 expected.put(b); expected.putShort((short)length); - for ( int i = 0 ; i < length ; ++i ) + for (int i = 0; i < length; ++i) { expected.put("*".getBytes()); } - + expected.flip(); - + Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(TextFrame.class,1); - + TextFrame pActual = (TextFrame)capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); } - - @Test - public void testGenerate127ByteTextCase1_1_4() - { - int length = 127; - - StringBuilder builder = new StringBuilder(); - - for ( int i = 0 ; i < length ; ++i) - { - builder.append("*"); - } - - TextFrame textFrame = new TextFrame(builder.toString()); - textFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(length+16); - generator.generate(actual, textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - - //expected.put((byte)((length>>8) & 0xFF)); - //expected.put((byte)(length & 0xFF)); - expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse127ByteTextCase1_1_4() { @@ -277,70 +380,26 @@ public class ABCase1_1 expected.put(b); expected.putShort((short)length); - for ( int i = 0 ; i < length ; ++i ) + for (int i = 0; i < length; ++i) { expected.put("*".getBytes()); } - + expected.flip(); - + Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(TextFrame.class,1); - + TextFrame pActual = (TextFrame)capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); } - - @Test - public void testGenerate128ByteTextCase1_1_5() - { - int length = 128; - - StringBuilder builder = new StringBuilder(); - - for ( int i = 0 ; i < length ; ++i) - { - builder.append("*"); - } - - TextFrame textFrame = new TextFrame(builder.toString()); - textFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(length+16); - generator.generate(actual, textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - - expected.put((byte)(length>>8)); - expected.put((byte)(length & 0xFF)); - //expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse128ByteTextCase1_1_5() { @@ -355,72 +414,31 @@ public class ABCase1_1 expected.put(b); expected.putShort((short)length); - for ( int i = 0 ; i < length ; ++i ) + for (int i = 0; i < length; ++i) { expected.put("*".getBytes()); } - + expected.flip(); - + Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(TextFrame.class,1); - + TextFrame pActual = (TextFrame)capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); } - - @Test - public void testGenerate65535ByteTextCase1_1_6() - { - int length = 65535; - - StringBuilder builder = new StringBuilder(); - - for ( int i = 0 ; i < length ; ++i) - { - builder.append("*"); - } - - TextFrame textFrame = new TextFrame(builder.toString()); - textFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(length+16); - generator.generate(actual, textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - expected.put(new byte[]{ (byte)0xff, (byte)0xff}); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse65535ByteTextCase1_1_6() { - //Debug.enableDebugLogging(Parser.class); - //Debug.enableDebugLogging(TextPayloadParser.class); + // Debug.enableDebugLogging(Parser.class); + // Debug.enableDebugLogging(TextPayloadParser.class); int length = 65535; @@ -431,13 +449,14 @@ public class ABCase1_1 byte b = 0x00; // no masking b |= 0x7E; expected.put(b); - expected.put(new byte[]{ (byte)0xff, (byte)0xff}); + expected.put(new byte[] + { (byte)0xff, (byte)0xff }); - for ( int i = 0 ; i < length ; ++i ) + for (int i = 0; i < length; ++i) { expected.put("*".getBytes()); } - + expected.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); policy.setMaxTextMessageSize(length); @@ -445,58 +464,15 @@ public class ABCase1_1 FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(TextFrame.class,1); - + TextFrame pActual = (TextFrame)capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); } - - - @Test - public void testGenerate65536ByteTextCase1_1_7() - { - int length = 65536; - - StringBuilder builder = new StringBuilder(); - - for ( int i = 0 ; i < length ; ++i) - { - builder.append("*"); - } - - TextFrame textFrame = new TextFrame(builder.toString()); - textFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(length+16); - generator.generate(actual, textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 11); - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= 0x7F; - expected.put(b); - expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}); - - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse65536ByteTextCase1_1_7() { @@ -509,27 +485,52 @@ public class ABCase1_1 byte b = 0x00; // no masking b |= 0x7F; expected.put(b); - expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}); + expected.put(new byte[] + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }); - for ( int i = 0 ; i < length ; ++i ) + for (int i = 0; i < length; ++i) { expected.put("*".getBytes()); } - + expected.flip(); - + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); policy.setMaxTextMessageSize(length); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(TextFrame.class,1); - + TextFrame pActual = (TextFrame)capture.getFrames().get(0); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("TextFrame.payload",length,pActual.getPayload()); + } + + @Test + public void testParseEmptyTextCase1_1_1() + { + + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x81, (byte)0x00 }); + + expected.flip(); + + Parser parser = new Parser(policy); + FrameParseCapture capture = new FrameParseCapture(); + parser.addListener(capture); + parser.parse(expected); + + capture.assertNoErrors(); + capture.assertHasFrame(TextFrame.class,1); + + TextFrame pActual = (TextFrame)capture.getFrames().get(0); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(0)); + ByteBufferAssert.assertSize("TextFrame.payload",0,pActual.getPayload()); } } diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1_2.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1_2.java index 7031eafa35e..685eecbcf55 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1_2.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/ab/ABCase1_2.java @@ -1,91 +1,41 @@ package org.eclipse.jetty.websocket.ab; - -import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.*; import java.nio.ByteBuffer; -import org.eclipse.jetty.io.StandardByteBufferPool; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.ByteBufferAssert; -import org.eclipse.jetty.websocket.Debug; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.frames.BinaryFrame; -import org.eclipse.jetty.websocket.frames.TextFrame; 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.parser.TextPayloadParser; import org.junit.Assert; import org.junit.Test; +/** + * Binary Message Spec testing the {@link Generator} and {@link Parser} + */ public class ABCase1_2 { - StandardByteBufferPool bufferPool = new StandardByteBufferPool(); - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - + private WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); - @Test - public void testGenerateEmptyBinaryCase1_2_1() - { - BinaryFrame binaryFrame = new BinaryFrame(new byte[]{}); - binaryFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(32); - generator.generate(actual, binaryFrame); - - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x82, (byte)0x00 }); - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - - @Test - public void testParseEmptyBinaryCase1_2_1() - { - - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x82, (byte)0x00 }); - - expected.flip(); - - Parser parser = new Parser(policy); - FrameParseCapture capture = new FrameParseCapture(); - parser.addListener(capture); - parser.parse(expected); - - capture.assertNoErrors(); - capture.assertHasFrame(BinaryFrame.class,1); - - BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0); - Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0)); - ByteBufferAssert.assertSize("BinaryFrame.payload",0,pActual.getPayload()); - } - @Test public void testGenerate125ByteBinaryCase1_2_2() { int length = 125; - + ByteBuffer bb = ByteBuffer.allocate(length); - + for ( int i = 0 ; i < length ; ++i) { bb.put("*".getBytes()); } - + bb.flip(); - + BinaryFrame binaryFrame = new BinaryFrame( BufferUtil.toArray(bb) ); binaryFrame.setFin(true); @@ -94,109 +44,314 @@ public class ABCase1_2 ByteBuffer actual = ByteBuffer.allocate(length + 11); generator.generate(actual, binaryFrame); - + ByteBuffer expected = ByteBuffer.allocate(length + 5); expected.put(new byte[] { (byte)0x82 }); - + byte b = 0x00; // no masking b |= length & 0x7F; expected.put(b); - + for ( int i = 0 ; i < length ; ++i ) { expected.put("*".getBytes()); } - + actual.flip(); expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - - @Test - public void testParse125ByteBinaryCase1_2_2() - { - int length = 125; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - expected.put(new byte[] - { (byte)0x82 }); - byte b = 0x00; // no masking - b |= length & 0x7F; - expected.put(b); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - Parser parser = new Parser(policy); - FrameParseCapture capture = new FrameParseCapture(); - parser.addListener(capture); - parser.parse(expected); - - capture.assertNoErrors(); - capture.assertHasFrame(BinaryFrame.class,1); - - BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0); - Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } - + @Test public void testGenerate126ByteBinaryCase1_2_3() { int length = 126; - + ByteBuffer bb = ByteBuffer.allocate(length); - + for ( int i = 0 ; i < length ; ++i) { bb.put("*".getBytes()); } - + bb.flip(); - + BinaryFrame binaryFrame = new BinaryFrame(BufferUtil.toArray(bb)); binaryFrame.setFin(true); - + Generator generator = new Generator(policy); - + ByteBuffer actual = ByteBuffer.allocate(length + 11); - + generator.generate(actual, binaryFrame); - + ByteBuffer expected = ByteBuffer.allocate(length + 5); expected.put(new byte[] { (byte)0x82 }); - + byte b = 0x00; // no masking b |= length & 0x7E; expected.put(b); - - //expected.put((byte)((length>>8) & 0xFF)); - //expected.put((byte)(length & 0xFF)); + + //expected.put((byte)((length>>8) & 0xFF)); + //expected.put((byte)(length & 0xFF)); expected.putShort((short)length); - + for ( int i = 0 ; i < length ; ++i ) { expected.put("*".getBytes()); } - + actual.flip(); expected.flip(); - + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - + } - + + @Test + public void testGenerate127ByteBinaryCase1_2_4() + { + int length = 127; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) + { + bb.put("*".getBytes()); + + } + + bb.flip(); + + BinaryFrame binaryFrame = new BinaryFrame(BufferUtil.toArray(bb)); + binaryFrame.setFin(true); + + Generator generator = new Generator(policy); + + ByteBuffer actual = ByteBuffer.allocate(length + 11); + generator.generate(actual, binaryFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + + //expected.put((byte)((length>>8) & 0xFF)); + //expected.put((byte)(length & 0xFF)); + expected.putShort((short)length); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testGenerate128ByteBinaryCase1_2_5() + { + int length = 128; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) + { + bb.put("*".getBytes()); + + } + + bb.flip(); + BinaryFrame textFrame = new BinaryFrame(BufferUtil.toArray(bb)); + textFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(length + 11); + generator.generate(actual, textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + + expected.put((byte)(length>>8)); + expected.put((byte)(length & 0xFF)); + //expected.putShort((short)length); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testGenerate65535ByteBinaryCase1_2_6() + { + int length = 65535; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) + { + bb.put("*".getBytes()); + + } + + bb.flip(); + + BinaryFrame textFrame = new BinaryFrame(BufferUtil.toArray(bb)); + textFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(length + 11); + generator.generate(actual, textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + expected.put(new byte[]{ (byte)0xff, (byte)0xff}); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testGenerate65536ByteBinaryCase1_2_7() + { + int length = 65536; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) + { + bb.put("*".getBytes()); + + } + + bb.flip(); + + BinaryFrame textFrame = new BinaryFrame(BufferUtil.toArray(bb)); + textFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(length + 32); + generator.generate(actual, textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 11); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= 0x7F; + expected.put(b); + expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}); + + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testGenerateEmptyBinaryCase1_2_1() + { + BinaryFrame binaryFrame = new BinaryFrame(new byte[]{}); + binaryFrame.setFin(true); + + Generator generator = new Generator(policy); + ByteBuffer actual = ByteBuffer.allocate(32); + generator.generate(actual, binaryFrame); + + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x82, (byte)0x00 }); + + actual.flip(); + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + @Test + public void testParse125ByteBinaryCase1_2_2() + { + int length = 125; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + byte b = 0x00; // no masking + b |= length & 0x7F; + expected.put(b); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + Parser parser = new Parser(policy); + FrameParseCapture capture = new FrameParseCapture(); + parser.addListener(capture); + parser.parse(expected); + + capture.assertNoErrors(); + capture.assertHasFrame(BinaryFrame.class,1); + + BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0); + Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); + ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); + } + @Test public void testParse126ByteBinaryCase1_2_3() { @@ -215,70 +370,22 @@ public class ABCase1_2 { expected.put("*".getBytes()); } - + expected.flip(); - + Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(BinaryFrame.class,1); - + BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); } - - @Test - public void testGenerate127ByteBinaryCase1_2_4() - { - int length = 127; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - - } - - bb.flip(); - - BinaryFrame binaryFrame = new BinaryFrame(BufferUtil.toArray(bb)); - binaryFrame.setFin(true); - - Generator generator = new Generator(policy); - - ByteBuffer actual = ByteBuffer.allocate(length + 11); - generator.generate(actual, binaryFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - - //expected.put((byte)((length>>8) & 0xFF)); - //expected.put((byte)(length & 0xFF)); - expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse127ByteBinaryCase1_2_4() { @@ -297,68 +404,22 @@ public class ABCase1_2 { expected.put("*".getBytes()); } - + expected.flip(); - + Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(BinaryFrame.class,1); - + BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); } - - @Test - public void testGenerate128ByteBinaryCase1_2_5() - { - int length = 128; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - - } - - bb.flip(); - BinaryFrame textFrame = new BinaryFrame(BufferUtil.toArray(bb)); - textFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(length + 11); - generator.generate(actual, textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - - expected.put((byte)(length>>8)); - expected.put((byte)(length & 0xFF)); - //expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse128ByteBinaryCase1_2_5() { @@ -377,69 +438,25 @@ public class ABCase1_2 { expected.put("*".getBytes()); } - + expected.flip(); - + Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(BinaryFrame.class,1); - + BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); } - - @Test - public void testGenerate65535ByteBinaryCase1_2_6() - { - int length = 65535; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - - } - - bb.flip(); - - BinaryFrame textFrame = new BinaryFrame(BufferUtil.toArray(bb)); - textFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(length + 11); - generator.generate(actual, textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - expected.put(new byte[]{ (byte)0xff, (byte)0xff}); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse65535ByteBinaryCase1_2_6() - { + { int length = 65535; ByteBuffer expected = ByteBuffer.allocate(length + 5); @@ -455,7 +472,7 @@ public class ABCase1_2 { expected.put("*".getBytes()); } - + expected.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); policy.setMaxTextMessageSize(length); @@ -463,61 +480,16 @@ public class ABCase1_2 FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(BinaryFrame.class,1); - + BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); } - - - @Test - public void testGenerate65536ByteBinaryCase1_2_7() - { - int length = 65536; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - - } - - bb.flip(); - - BinaryFrame textFrame = new BinaryFrame(BufferUtil.toArray(bb)); - textFrame.setFin(true); - - Generator generator = new Generator(policy); - ByteBuffer actual = ByteBuffer.allocate(length + 32); - generator.generate(actual, textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 11); - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= 0x7F; - expected.put(b); - expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - actual.flip(); - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - @Test public void testParse65536ByteBinaryCase1_2_7() { @@ -536,21 +508,45 @@ public class ABCase1_2 { expected.put("*".getBytes()); } - + expected.flip(); - + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); policy.setMaxTextMessageSize(length); Parser parser = new Parser(policy); FrameParseCapture capture = new FrameParseCapture(); parser.addListener(capture); parser.parse(expected); - + capture.assertNoErrors(); capture.assertHasFrame(BinaryFrame.class,1); - + BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0); Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); + ByteBufferAssert.assertSize("BinaryFrame.payload",length,pActual.getPayload()); + } + + @Test + public void testParseEmptyBinaryCase1_2_1() + { + + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x82, (byte)0x00 }); + + expected.flip(); + + Parser parser = new Parser(policy); + FrameParseCapture capture = new FrameParseCapture(); + parser.addListener(capture); + parser.parse(expected); + + capture.assertNoErrors(); + capture.assertHasFrame(BinaryFrame.class,1); + + BinaryFrame pActual = (BinaryFrame)capture.getFrames().get(0); + Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0)); + ByteBufferAssert.assertSize("BinaryFrame.payload",0,pActual.getPayload()); } } 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 d71861cbc87..d6a81f912f5 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 @@ -5,7 +5,6 @@ import static org.hamcrest.Matchers.*; import java.nio.ByteBuffer; import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.websocket.Debug; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; @@ -18,8 +17,6 @@ public class ClosePayloadParserTest @Test public void testGameOver() { - Debug.enableDebugLogging(Parser.class); - Debug.enableDebugLogging(ClosePayloadParser.class); String expectedReason = "Game Over"; byte utf[] = expectedReason.getBytes(StringUtil.__UTF8_CHARSET); 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 ffe47f602b1..a40cabcf8f2 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 @@ -61,10 +61,10 @@ public class TextPayloadParserTest Assert.assertThat("Must be a long length payload",utf.length,greaterThan(0xFFFF)); - ByteBuffer buf = ByteBuffer.allocate(utf.length + 10); + ByteBuffer buf = ByteBuffer.allocate(utf.length + 32); buf.put((byte)0x81); - buf.put((byte)(0x80 | 0x7F)); // 0x7F == 127 (a 4 byte payload length) - buf.putInt(utf.length); + buf.put((byte)(0x80 | 0x7F)); // 0x7F == 127 (a 8 byte payload length) + buf.putLong(utf.length); MaskedByteBuffer.putMask(buf); MaskedByteBuffer.putPayload(buf,utf); buf.flip(); 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 849673c8a38..ad352dc3412 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 @@ -178,7 +178,7 @@ public class WebSocketMessageRFC6455Test } - private static final int WSVERSION = org.eclipse.jetty.websocket.api.WebSocket.VERSION; + private static final int WSVERSION = 13; // RFC-6455 version private static Server __server; private static SelectChannelConnector __connector; private static TestWebSocket __serverWebSocket; @@ -199,13 +199,13 @@ public class WebSocketMessageRFC6455Test { __textCount.set(0); __serverWebSocket = new TestWebSocket(); - __serverWebSocket._onConnect=("onConnect".equals(protocol)); - __serverWebSocket._echo=("echo".equals(protocol)); - __serverWebSocket._aggregate=("aggregate".equals(protocol)); - __serverWebSocket._latch=("latch".equals(protocol)); + __serverWebSocket._onConnect = ("onConnect".equals(protocol)); + __serverWebSocket._echo = ("echo".equals(protocol)); + __serverWebSocket._aggregate = ("aggregate".equals(protocol)); + __serverWebSocket._latch = ("latch".equals(protocol)); if (__serverWebSocket._latch) { - __latch=new CountDownLatch(1); + __latch = new CountDownLatch(1); } return __serverWebSocket; } @@ -217,7 +217,6 @@ public class WebSocketMessageRFC6455Test __server.start(); } - @AfterClass public static void stopServer() throws Exception { @@ -225,79 +224,70 @@ public class WebSocketMessageRFC6455Test __server.join(); } - private void lookFor(String string,InputStream in) - throws IOException - { - String orig=string; - Utf8StringBuilder scanned=new Utf8StringBuilder(); + private void lookFor(String string, InputStream in) throws IOException + { + String orig = string; + Utf8StringBuilder scanned = new Utf8StringBuilder(); try { - while(true) + while (true) { int b = in.read(); - if (b<0) + if (b < 0) { throw new EOFException(); } scanned.append((byte)b); - assertEquals("looking for\""+orig+"\" in '"+scanned+"'",string.charAt(0),b); - if (string.length()==1) + assertEquals("looking for\"" + orig + "\" in '" + scanned + "'",string.charAt(0),b); + if (string.length() == 1) { break; } - string=string.substring(1); + string = string.substring(1); } } - catch(IOException e) + catch (IOException e) { - System.err.println("IOE while looking for \""+orig+"\" in '"+scanned+"'"); + System.err.println("IOE while looking for \"" + orig + "\" in '" + scanned + "'"); throw e; } - } + } - private void skipTo(String string,InputStream in) - throws IOException - { - int state=0; + private void skipTo(String string, InputStream in) throws IOException + { + int state = 0; - while(true) + while (true) { int b = in.read(); - if (b<0) + if (b < 0) { throw new EOFException(); } - if (b==string.charAt(state)) + if (b == string.charAt(state)) { state++; - if (state==string.length()) + if (state == string.length()) { break; } } else { - state=0; + state = 0; } } - } + } @Test public void testBinaryAggregate() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: aggregate\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: aggregate\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); socket.setSoTimeout(1000); @@ -318,10 +308,10 @@ public class WebSocketMessageRFC6455Test output.write(0xff); output.write(0xff); output.write(0xff); - byte[] bytes="0123456789".getBytes(StringUtil.__ISO_8859_1); + byte[] bytes = "0123456789".getBytes(StringUtil.__ISO_8859_1); for (byte b : bytes) { - output.write(b^0xff); + output.write(b ^ 0xff); } output.flush(); @@ -333,7 +323,7 @@ public class WebSocketMessageRFC6455Test output.write(0xff); for (byte b : bytes) { - output.write(b^0xff); + output.write(b ^ 0xff); } output.flush(); @@ -342,38 +332,30 @@ public class WebSocketMessageRFC6455Test lookFor("01234567890123456789",input); } - @Test public void testBlockedConsumer() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - byte[] bytes="This is a long message of text that we will send again and again".getBytes(StringUtil.__ISO_8859_1); - byte[] mesg=new byte[bytes.length+6]; + byte[] bytes = "This is a long message of text that we will send again and again".getBytes(StringUtil.__ISO_8859_1); + byte[] mesg = new byte[bytes.length + 6]; mesg[0] = (byte)(0x80 + OpCode.TEXT.getCode()); - mesg[1]=(byte)(0x80+bytes.length); - mesg[2]=(byte)0xff; - mesg[3]=(byte)0xff; - mesg[4]=(byte)0xff; - mesg[5]=(byte)0xff; - for (int i=0;i>> "+i); output.flush(); - long now=System.currentTimeMillis(); - long duration=now-start; - start=now; - if (max2000); // was blocked + assertEquals(count + 1,__textCount.get()); // all messages + assertTrue(max > 2000); // was blocked } @Test public void testBlockedProducer() throws Exception { - final Socket socket = new Socket("localhost", __connector.getLocalPort()); + final Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); final int count = 100000; - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: latch\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: latch\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); // Make sure the read times out if there are problems with the implementation @@ -484,7 +459,7 @@ public class WebSocketMessageRFC6455Test __latch.countDown(); // wait 2s and then consume messages - final AtomicLong totalB=new AtomicLong(); + final AtomicLong totalB = new AtomicLong(); new Thread() { @Override @@ -494,120 +469,86 @@ public class WebSocketMessageRFC6455Test { Thread.sleep(2000); - byte[] recv = new byte[32*1024]; + byte[] recv = new byte[32 * 1024]; - int len=0; - while (len>=0) + int len = 0; + while (len >= 0) { totalB.addAndGet(len); - len=socket.getInputStream().read(recv,0,recv.length); + len = socket.getInputStream().read(recv,0,recv.length); Thread.sleep(10); } } - catch(Exception e) + catch (Exception e) { e.printStackTrace(); } } }.start(); - // Send enough messages to fill receive buffer - long max=0; - long start=System.currentTimeMillis(); - String mesg="How Now Brown Cow"; - for (int i=0;i0) + if (code > 0) { - output.write(code/0x100); - output.write(code%0x100); + output.write(code / 0x100); + output.write(code % 0x100); output.write(m.getBytes()); } output.flush(); @@ -644,17 +585,17 @@ public class WebSocketMessageRFC6455Test byte[] buf = new byte[128]; int len = input.read(buf); - assertEquals(tst,2+tests[t][1],len); + assertEquals(tst,2 + tests[t][1],len); assertEquals(tst,(byte)0x88,buf[0]); - if (len>=4) + if (len >= 4) { - code=((0xff&buf[2])*0x100)+(0xff&buf[3]); + code = ((0xff & buf[2]) * 0x100) + (0xff & buf[3]); assertEquals(tst,tests[t][2],code); - if (len>4) + if (len > 4) { - m = new String(buf,4,len-4,"UTF-8"); + m = new String(buf,4,len - 4,"UTF-8"); assertEquals(tst,resp[t],m); } } @@ -663,7 +604,6 @@ public class WebSocketMessageRFC6455Test assertEquals(tst,tests[t][2],-1); } - len = input.read(buf); assertEquals(tst,-1,len); } @@ -673,52 +613,31 @@ public class WebSocketMessageRFC6455Test public void testCloseOut() throws Exception { int[][] tests = - { - {-1,0,-1}, - {-1,0,-1}, - {0,2,1000}, - {0,2+4,1000}, - {1000,2,1000}, - {1000,2+4,1000}, - {1005,0,-1}, - {1005,0,-1}, - {1006,0,-1}, - {1006,0,-1}, - {9000,2,9000}, - {9000,2+4,9000} - }; + { + { -1, 0, -1 }, + { -1, 0, -1 }, + { 0, 2, 1000 }, + { 0, 2 + 4, 1000 }, + { 1000, 2, 1000 }, + { 1000, 2 + 4, 1000 }, + { 1005, 0, -1 }, + { 1005, 0, -1 }, + { 1006, 0, -1 }, + { 1006, 0, -1 }, + { 9000, 2, 9000 }, + { 9000, 2 + 4, 9000 } }; String[] mesg = - { - null, - "Not Sent", - null, - "mesg", - null, - "mesg", - null, - "mesg", - null, - "mesg", - null, - "mesg" - }; + { null, "Not Sent", null, "mesg", null, "mesg", null, "mesg", null, "mesg", null, "mesg" }; - for (int t=0;t=4) + if (len >= 4) { - int code=((0xff&buf[2])*0x100)+(0xff&buf[3]); + int code = ((0xff & buf[2]) * 0x100) + (0xff & buf[3]); assertEquals(tst,tests[t][2],code); - if (len>4) + if (len > 4) { - String m = new String(buf,4,len-4,"UTF-8"); + String m = new String(buf,4,len - 4,"UTF-8"); assertEquals(tst,mesg[t],m); } } @@ -765,9 +684,9 @@ public class WebSocketMessageRFC6455Test output.write(0x00); output.flush(); } - catch(IOException e) + catch (IOException e) { - System.err.println("socket "+socket); + System.err.println("socket " + socket); throw e; } @@ -779,20 +698,12 @@ public class WebSocketMessageRFC6455Test @Test public void testDeflateFrameExtension() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: echo\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "Sec-WebSocket-Extensions: x-deflate-frame;minLength=64\r\n"+ - "Sec-WebSocket-Extensions: fragment;minFragments=2\r\n"+ - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: echo\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "Sec-WebSocket-Extensions: x-deflate-frame;minLength=64\r\n" + + "Sec-WebSocket-Extensions: fragment;minFragments=2\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); // Make sure the read times out if there are problems with the implementation @@ -811,37 +722,36 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - // Server sends a big message String text = "0123456789ABCDEF "; - text=text+text+text+text; - text=text+text+text+text; - text=text+text+text+text+'X'; - byte[] data=text.getBytes("utf-8"); + text = text + text + text + text; + text = text + text + text + text; + text = text + text + text + text + 'X'; + byte[] data = text.getBytes("utf-8"); Deflater deflater = new Deflater(); deflater.setInput(data); deflater.finish(); - byte[] buf=new byte[data.length]; + byte[] buf = new byte[data.length]; - buf[0]=((byte)0x7e); - buf[1]=(byte)(data.length>>8); - buf[2]=(byte)(data.length&0xff); + buf[0] = ((byte)0x7e); + buf[1] = (byte)(data.length >> 8); + buf[2] = (byte)(data.length & 0xff); - int l=deflater.deflate(buf,3,buf.length-3); + int l = deflater.deflate(buf,3,buf.length - 3); assertTrue(deflater.finished()); output.write(0xC1); - output.write((byte)(0x80|(0xff&(l+3)))); + output.write((byte)(0x80 | (0xff & (l + 3)))); output.write(0x00); output.write(0x00); output.write(0x00); output.write(0x00); - output.write(buf,0,l+3); + output.write(buf,0,l + 3); output.flush(); assertEquals(0x40 + OpCode.TEXT.getCode(),input.read()); - assertEquals(0x20+3,input.read()); + assertEquals(0x20 + 3,input.read()); assertEquals(0x7e,input.read()); assertEquals(0x02,input.read()); assertEquals(0x20,input.read()); @@ -856,9 +766,8 @@ public class WebSocketMessageRFC6455Test assertEquals(544,inflater.inflate(result)); assertEquals(TypeUtil.toHexString(data,0,544),TypeUtil.toHexString(result)); - assertEquals((byte)0xC0,(byte)input.read()); - assertEquals(0x21+3,input.read()); + assertEquals(0x21 + 3,input.read()); assertEquals(0x7e,input.read()); assertEquals(0x02,input.read()); assertEquals(0x21,input.read()); @@ -871,25 +780,17 @@ public class WebSocketMessageRFC6455Test assertEquals(545,inflater.inflate(result)); assertEquals(TypeUtil.toHexString(data,544,545),TypeUtil.toHexString(result)); - } @Test public void testFragmentExtension() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: onConnect\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "Sec-WebSocket-Extensions: fragment;maxLength=4;minFragments=7\r\n"+ - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: onConnect\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "Sec-WebSocket-Extensions: fragment;maxLength=4;minFragments=7\r\n" + "\r\n") + .getBytes("ISO-8859-1")); output.flush(); // Make sure the read times out if there are problems with the implementation @@ -937,20 +838,12 @@ public class WebSocketMessageRFC6455Test @Test public void testIdentityExtension() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: onConnect\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "Sec-WebSocket-Extensions: identity;param=0\r\n"+ - "Sec-WebSocket-Extensions: identity;param=1, identity ; param = '2' ; other = ' some = value ' \r\n"+ - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: onConnect\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "Sec-WebSocket-Extensions: identity;param=0\r\n" + + "Sec-WebSocket-Extensions: identity;param=1, identity ; param = '2' ; other = ' some = value ' \r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); // Make sure the read times out if there are problems with the implementation @@ -976,22 +869,14 @@ public class WebSocketMessageRFC6455Test lookFor("sent on connect",input); } - @Test public void testIdle() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: onConnect\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: onConnect\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); // Make sure the read times out if there are problems with the implementation @@ -1013,27 +898,26 @@ public class WebSocketMessageRFC6455Test assertEquals((byte)0x88,(byte)input.read()); assertEquals(26,input.read()); - assertEquals(1000/0x100,input.read()); - assertEquals(1000%0x100,input.read()); + assertEquals(1000 / 0x100,input.read()); + assertEquals(1000 % 0x100,input.read()); lookFor("Idle",input); // respond to close - output.write(0x88^0xff); - output.write(0x80^0xff); + output.write(0x88 ^ 0xff); + output.write(0x80 ^ 0xff); output.write(0xff); output.write(0xff); output.write(0xff); output.write(0xff); output.flush(); - assertTrue(__serverWebSocket.awaitDisconnected(5000)); try { __serverWebSocket.connection.sendMessage("Don't send"); assertTrue(false); } - catch(IOException e) + catch (IOException e) { assertTrue(true); } @@ -1042,18 +926,11 @@ public class WebSocketMessageRFC6455Test @Test public void testMaxBinarySize() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: other\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: other\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); socket.setSoTimeout(100000); @@ -1075,10 +952,10 @@ public class WebSocketMessageRFC6455Test output.write(0xff); output.write(0xff); output.write(0xff); - byte[] bytes="0123456789".getBytes(StringUtil.__ISO_8859_1); + byte[] bytes = "0123456789".getBytes(StringUtil.__ISO_8859_1); for (byte b : bytes) { - output.write(b^0xff); + output.write(b ^ 0xff); } output.flush(); @@ -1090,14 +967,13 @@ public class WebSocketMessageRFC6455Test output.write(0xff); for (byte b : bytes) { - output.write(b^0xff); + output.write(b ^ 0xff); } output.flush(); - assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read()); assertEquals(19,input.read()); - int code=((0xff&input.read())*0x100)+(0xff&input.read()); + int code = ((0xff & input.read()) * 0x100) + (0xff & input.read()); assertEquals(StatusCode.MESSAGE_TOO_LARGE,code); lookFor("Message size > 15",input); } @@ -1105,18 +981,11 @@ public class WebSocketMessageRFC6455Test @Test public void testMaxBinarySize2() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: other\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: other\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); socket.setSoTimeout(100000); @@ -1138,37 +1007,28 @@ public class WebSocketMessageRFC6455Test output.write(0xff); output.write(0xff); output.write(0xff); - byte[] bytes="01234567890123456789".getBytes(StringUtil.__ISO_8859_1); + byte[] bytes = "01234567890123456789".getBytes(StringUtil.__ISO_8859_1); for (byte b : bytes) { - output.write(b^0xff); + output.write(b ^ 0xff); } output.flush(); assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read()); assertEquals(19,input.read()); - int code=((0xff&input.read())*0x100)+(0xff&input.read()); + int code = ((0xff & input.read()) * 0x100) + (0xff & input.read()); assertEquals(StatusCode.MESSAGE_TOO_LARGE,code); lookFor("Message size > 15",input); } - - @Test public void testMaxTextSize() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: other\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: other\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); socket.setSoTimeout(1000); @@ -1190,10 +1050,10 @@ public class WebSocketMessageRFC6455Test output.write(0xff); output.write(0xff); output.write(0xff); - byte[] bytes="0123456789".getBytes(StringUtil.__ISO_8859_1); + byte[] bytes = "0123456789".getBytes(StringUtil.__ISO_8859_1); for (byte b : bytes) { - output.write(b^0xff); + output.write(b ^ 0xff); } output.flush(); @@ -1205,34 +1065,25 @@ public class WebSocketMessageRFC6455Test output.write(0xff); for (byte b : bytes) { - output.write(b^0xff); + output.write(b ^ 0xff); } output.flush(); assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read()); assertEquals(30,input.read()); - int code=((0xff&input.read())*0x100)+(0xff&input.read()); + int code = ((0xff & input.read()) * 0x100) + (0xff & input.read()); assertEquals(StatusCode.MESSAGE_TOO_LARGE,code); lookFor("Text message size > 15 chars",input); } - - @Test public void testMaxTextSize2() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: other\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: other\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); socket.setSoTimeout(100000); @@ -1254,38 +1105,28 @@ public class WebSocketMessageRFC6455Test output.write(0xff); output.write(0xff); output.write(0xff); - byte[] bytes="01234567890123456789".getBytes(StringUtil.__ISO_8859_1); + byte[] bytes = "01234567890123456789".getBytes(StringUtil.__ISO_8859_1); for (byte b : bytes) { - output.write(b^0xff); + output.write(b ^ 0xff); } output.flush(); - - assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read()); assertEquals(30,input.read()); - int code=((0xff&input.read())*0x100)+(0xff&input.read()); + int code = ((0xff & input.read()) * 0x100) + (0xff & input.read()); assertEquals(StatusCode.MESSAGE_TOO_LARGE,code); lookFor("Text message size > 15 chars",input); } - @Test public void testMaxTextSizeFalseFrag() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: other\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: other\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); socket.setSoTimeout(1000); @@ -1299,28 +1140,27 @@ public class WebSocketMessageRFC6455Test assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); - __serverWebSocket.getConnection().setMaxTextMessageSize(10*1024); + __serverWebSocket.getConnection().setMaxTextMessageSize(10 * 1024); __serverWebSocket.getConnection().setAllowFrameFragmentation(true); output.write(0x81); - output.write(0x80|0x7E); - output.write((byte)((16*1024)>>8)); - output.write((byte)((16*1024)&0xff)); + output.write(0x80 | 0x7E); + output.write((byte)((16 * 1024) >> 8)); + output.write((byte)((16 * 1024) & 0xff)); output.write(0x00); output.write(0x00); output.write(0x00); output.write(0x00); - for (int i=0;i<(16*1024);i++) + for (int i = 0; i < (16 * 1024); i++) { output.write('X'); } output.flush(); - assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read()); assertEquals(33,input.read()); - int code=((0xff&input.read())*0x100)+(0xff&input.read()); + int code = ((0xff & input.read()) * 0x100) + (0xff & input.read()); assertEquals(StatusCode.MESSAGE_TOO_LARGE,code); lookFor("Text message size > 10240 chars",input); } @@ -1328,18 +1168,11 @@ public class WebSocketMessageRFC6455Test @Test public void testNotUTF8() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: chat\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: chat\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); socket.setSoTimeout(100000); @@ -1367,7 +1200,7 @@ public class WebSocketMessageRFC6455Test assertEquals(0x80 | OpCode.CLOSE.getCode(),input.read()); assertEquals(15,input.read()); - int code=((0xff&input.read())*0x100)+(0xff&input.read()); + int code = ((0xff & input.read()) * 0x100) + (0xff & input.read()); assertEquals(StatusCode.BAD_PAYLOAD,code); lookFor("Invalid UTF-8",input); } @@ -1375,18 +1208,11 @@ public class WebSocketMessageRFC6455Test @Test public void testServerEcho() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: echo\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: echo\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); output.write(0x84); output.write(0x8f); @@ -1394,10 +1220,10 @@ public class WebSocketMessageRFC6455Test output.write(0xff); output.write(0xff); output.write(0xff); - byte[] bytes="this is an echo".getBytes(StringUtil.__ISO_8859_1); + byte[] bytes = "this is an echo".getBytes(StringUtil.__ISO_8859_1); for (byte b : bytes) { - output.write(b^0xff); + output.write(b ^ 0xff); } output.flush(); // Make sure the read times out if there are problems with the implementation @@ -1418,24 +1244,15 @@ public class WebSocketMessageRFC6455Test lookFor("this is an echo",input); } - - @Test public void testServerPingPong() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); // Make sure the read times out if there are problems with the implementation OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: echo\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: echo\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); output.write(0x89); output.write(0x80); @@ -1463,18 +1280,11 @@ public class WebSocketMessageRFC6455Test @Test public void testServerSendBigStringMessage() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: chat, superchat\r\n"+ - "Sec-WebSocket-Version: "+org.eclipse.jetty.websocket.api.WebSocket.VERSION+"\r\n"+ - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + + "Sec-WebSocket-Protocol: chat, superchat\r\n" + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); // Make sure the read times out if there are problems with the implementation @@ -1497,7 +1307,7 @@ public class WebSocketMessageRFC6455Test { message.append(text); } - String data=message.toString(); + String data = message.toString(); __serverWebSocket.connection.sendMessage(data); assertEquals(OpCode.TEXT.getCode(),input.read()); @@ -1510,22 +1320,14 @@ public class WebSocketMessageRFC6455Test lookFor(data.substring(0x1ff6),input); } - @Test public void testServerSendOnConnect() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: onConnect\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: onConnect\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); // Make sure the read times out if there are problems with the implementation @@ -1549,18 +1351,11 @@ public class WebSocketMessageRFC6455Test @Test public void testTCPClose() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: onConnect\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: onConnect\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); // Make sure the read times out if there are problems with the implementation @@ -1573,7 +1368,6 @@ public class WebSocketMessageRFC6455Test lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); skipTo("\r\n\r\n",input); - assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); @@ -1589,28 +1383,20 @@ public class WebSocketMessageRFC6455Test __serverWebSocket.connection.sendMessage("Don't send"); assertTrue(false); } - catch(IOException e) + catch (IOException e) { assertTrue(true); } } - @Test public void testTCPHalfClose() throws Exception { - Socket socket = new Socket("localhost", __connector.getLocalPort()); + Socket socket = new Socket("localhost",__connector.getLocalPort()); OutputStream output = socket.getOutputStream(); - output.write( - ("GET /chat HTTP/1.1\r\n"+ - "Host: server.example.com\r\n"+ - "Upgrade: websocket\r\n"+ - "Connection: Upgrade\r\n"+ - "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+ - "Sec-WebSocket-Origin: http://example.com\r\n"+ - "Sec-WebSocket-Protocol: onConnect\r\n" + - "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + - "\r\n").getBytes("ISO-8859-1")); + output.write(("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n" + "Sec-WebSocket-Protocol: onConnect\r\n" + + "Sec-WebSocket-Version: " + WSVERSION + "\r\n" + "\r\n").getBytes("ISO-8859-1")); output.flush(); // Make sure the read times out if there are problems with the implementation @@ -1623,7 +1409,6 @@ public class WebSocketMessageRFC6455Test lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input); skipTo("\r\n\r\n",input); - assertTrue(__serverWebSocket.awaitConnected(1000)); assertNotNull(__serverWebSocket.connection); @@ -1642,13 +1427,13 @@ public class WebSocketMessageRFC6455Test // look for broken pipe try { - for (int i=0;i<1000;i++) + for (int i = 0; i < 1000; i++) { output.write(0); } Assert.fail(); } - catch(SocketException e) + catch (SocketException e) { // expected }