From fa10576bc6ae3984415683f1e47e15710a4632c0 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 5 Apr 2017 17:30:51 -0700 Subject: [PATCH] Issue #207 - initial pass through for Stream backpressure --- .../jetty/util/SharedBlockingCallback.java | 2 +- .../jsr356/function/JsrEndpointFunctions.java | 8 +- .../websocket/jsr356/JsrSessionTest.java | 14 ++- ...tFunctions_OnMessage_BinaryStreamTest.java | 5 +- ...ndpointFunctions_OnMessage_BinaryTest.java | 4 +- ...intFunctions_OnMessage_TextStreamTest.java | 6 +- ...rEndpointFunctions_OnMessage_TextTest.java | 4 +- ...intFunctions_OnMessage_TextStreamTest.java | 8 +- .../jetty/websocket/api/FrameCallback.java | 53 ++++++++ .../eclipse/jetty/websocket/api/Session.java | 6 +- .../jetty/websocket/api/WebSocketPolicy.java | 3 + .../jetty/websocket/api/WriteCallback.java | 18 ++- .../api/extensions/IncomingFrames.java | 30 ++++- .../api/extensions/OutgoingFrames.java | 5 +- .../client/WebSocketUpgradeRequest.java | 30 ++--- .../client/io/WebSocketClientConnection.java | 16 +-- .../websocket/client/ClientConnectTest.java | 15 ++- .../common/BlockingWriteCallback.java | 14 +-- .../websocket/common/LogicalConnection.java | 21 +--- .../jetty/websocket/common/Parser.java | 98 ++++----------- .../common/WebSocketRemoteEndpoint.java | 5 +- .../websocket/common/WebSocketSession.java | 27 +++-- .../common/extensions/AbstractExtension.java | 8 +- .../common/extensions/ExtensionStack.java | 32 ++--- .../extensions/FrameCaptureExtension.java | 7 +- .../compress/CompressExtension.java | 34 +++--- .../compress/DeflateFrameExtension.java | 7 +- .../compress/PerMessageDeflateExtension.java | 14 +-- .../fragment/FragmentExtension.java | 32 ++--- .../identity/IdentityExtension.java | 8 +- .../function/CommonEndpointFunctions.java | 19 +-- .../common/function/EndpointFunctions.java | 7 +- .../io/AbstractWebSocketConnection.java | 49 ++++++-- .../websocket/common/io/FrameFlusher.java | 16 +-- .../jetty/websocket/common/io/FramePipes.java | 18 +-- .../common/message/ByteArrayMessageSink.java | 32 +++-- .../common/message/FrameCallbackBuffer.java | 35 ++++++ .../message/InputStreamMessageSink.java | 9 +- .../common/message/MessageInputStream.java | 36 ++++-- .../common/message/MessageReader.java | 12 +- .../websocket/common/message/MessageSink.java | 17 ++- .../common/message/MessageWriter.java | 11 +- .../message/PartialBinaryMessageSink.java | 16 ++- .../message/PartialTextMessageSink.java | 16 ++- .../common/message/ReaderMessageSink.java | 9 +- .../common/message/StringMessageSink.java | 13 +- .../common/ClosePayloadParserTest.java | 3 +- .../common/FrameCallbackAdapter.java | 25 ++++ .../common/GeneratorParserRoundtripTest.java | 6 +- .../jetty/websocket/common/GeneratorTest.java | 3 +- .../jetty/websocket/common/ParserTest.java | 44 ++++--- .../common/PingPayloadParserTest.java | 3 +- .../common/RFC6455ExamplesParserTest.java | 21 ++-- .../common/TextPayloadParserTest.java | 39 +++--- .../websocket/common/ab/TestABCase1_1.java | 31 ++--- .../websocket/common/ab/TestABCase1_2.java | 31 ++--- .../websocket/common/ab/TestABCase2.java | 40 +++--- .../websocket/common/ab/TestABCase4.java | 114 +++++------------- .../websocket/common/ab/TestABCase7_3.java | 69 ++++------- .../extensions/DummyIncomingFrames.java | 3 +- .../extensions/DummyOutgoingFrames.java | 6 +- .../common/extensions/ExtensionTool.java | 13 +- .../extensions/FragmentExtensionTest.java | 5 +- .../extensions/IdentityExtensionTest.java | 3 +- .../compress/CapturedHexPayloads.java | 6 +- .../compress/DeflateFrameExtensionTest.java | 15 ++- .../PerMessageDeflateExtensionTest.java | 5 +- .../function/CommonEndpointFunctionsTest.java | 23 ++-- .../common/io/LocalWebSocketConnection.java | 31 +---- .../message/MessageInputStreamTest.java | 51 ++++---- .../message/MessageOutputStreamTest.java | 23 ++-- .../common/message/MessageWriterTest.java | 12 +- .../common/test/BlockheadClient.java | 23 ++-- .../test/BlockheadServerConnection.java | 28 ++--- .../common/test/DummyConnection.java | 14 +-- .../common/test/IncomingFramesCapture.java | 30 +++-- .../common/test/OutgoingFramesCapture.java | 12 +- .../test/OutgoingNetworkBytesCapture.java | 6 +- .../websocket/common/test/UnitParser.java | 10 +- .../test/resources/jetty-logging.properties | 2 +- .../server/WebSocketServerConnection.java | 12 +- .../server/WebSocketServerFactory.java | 3 +- 82 files changed, 837 insertions(+), 777 deletions(-) create mode 100644 jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/FrameCallback.java create mode 100644 jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/FrameCallbackBuffer.java create mode 100644 jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/FrameCallbackAdapter.java diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/SharedBlockingCallback.java b/jetty-util/src/main/java/org/eclipse/jetty/util/SharedBlockingCallback.java index bb7b504b9aa..d839ad50667 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/SharedBlockingCallback.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/SharedBlockingCallback.java @@ -29,7 +29,6 @@ import java.util.concurrent.locks.ReentrantLock; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.thread.Invocable.InvocationType; /** * Provides a reusable {@link Callback} that can block the thread @@ -168,6 +167,7 @@ public class SharedBlockingCallback } else { + cause.printStackTrace(System.err); throw new IllegalStateException(_state); } } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java index 5a139724b13..5b1a40903e6 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java @@ -49,9 +49,11 @@ import javax.websocket.Session; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.InvalidWebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.function.CommonEndpointFunctions; import org.eclipse.jetty.websocket.common.message.MessageSink; @@ -105,11 +107,11 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions this.messageHandler = messageHandler; this.delegateSink = messageSink; } - + @Override - public void accept(ByteBuffer payload, Boolean fin) + public void accept(Frame frame, FrameCallback callback) { - this.delegateSink.accept(payload, fin); + this.delegateSink.accept(frame, callback); } @Override diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/JsrSessionTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/JsrSessionTest.java index 24e5a3d43b4..33fa9b493a2 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/JsrSessionTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/JsrSessionTest.java @@ -31,7 +31,9 @@ import javax.websocket.DeploymentException; import javax.websocket.MessageHandler; import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.common.FrameCallbackAdapter; import org.eclipse.jetty.websocket.common.frames.BinaryFrame; import org.eclipse.jetty.websocket.common.frames.ContinuationFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; @@ -125,9 +127,11 @@ public class JsrSessionTest session.addMessageHandler(String.class, (msg) -> received.add(msg)); session.open(); + + FrameCallback callback = new FrameCallbackAdapter(); - session.incomingFrame(new TextFrame().setPayload("G'day").setFin(true)); - session.incomingFrame(new TextFrame().setPayload("Hello World").setFin(true)); + session.incomingFrame(new TextFrame().setPayload("G'day").setFin(true), callback); + session.incomingFrame(new TextFrame().setPayload("Hello World").setFin(true), callback); assertThat("Received msgs", received.size(), is(2)); assertThat("Received Message[0]", received.get(0), is("G'day")); @@ -155,8 +159,10 @@ public class JsrSessionTest session.open(); - session.incomingFrame(new BinaryFrame().setPayload("G'day").setFin(false)); - session.incomingFrame(new ContinuationFrame().setPayload(" World").setFin(true)); + FrameCallback callback = new FrameCallbackAdapter(); + + session.incomingFrame(new BinaryFrame().setPayload("G'day").setFin(false), callback); + session.incomingFrame(new ContinuationFrame().setPayload(" World").setFin(true), callback); assertThat("Received partial", received.size(), is(2)); assertThat("Received Message[0].buffer", BufferUtil.toUTF8String((ByteBuffer) received.get(0)[0]), is("G'day")); diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryStreamTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryStreamTest.java index 6f780b471a9..c823f29d587 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryStreamTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryStreamTest.java @@ -31,9 +31,10 @@ import javax.websocket.ClientEndpointConfig; import javax.websocket.EndpointConfig; import javax.websocket.OnMessage; -import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.common.frames.BinaryFrame; import org.eclipse.jetty.websocket.common.function.EndpointFunctions; import org.eclipse.jetty.websocket.common.test.DummyConnection; import org.eclipse.jetty.websocket.jsr356.ClientContainer; @@ -130,7 +131,7 @@ public class JsrEndpointFunctions_OnMessage_BinaryStreamTest { TrackingSocket socket = performOnMessageInvocation(new MessageStreamSocket(), (endpoint) -> { - endpoint.onBinary(BufferUtil.toBuffer("Hello World", StandardCharsets.UTF_8), true); + endpoint.onBinary(new BinaryFrame().setPayload("Hello World").setFin(true), new FrameCallback.Adapter()); return null; }); socket.assertEvent("onMessage(MessageInputStream) = \"Hello World\""); diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryTest.java index 81b177a8dc2..e377b3f8ca8 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryTest.java @@ -34,8 +34,10 @@ import javax.websocket.OnMessage; import javax.websocket.Session; import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.InvalidSignatureException; +import org.eclipse.jetty.websocket.common.frames.BinaryFrame; import org.eclipse.jetty.websocket.common.test.DummyConnection; import org.eclipse.jetty.websocket.jsr356.ClientContainer; import org.eclipse.jetty.websocket.jsr356.ConfiguredEndpoint; @@ -107,7 +109,7 @@ public class JsrEndpointFunctions_OnMessage_BinaryTest // This invocation is the same for all tests ByteBuffer byteBuffer = ByteBuffer.wrap("Hello World".getBytes(StandardCharsets.UTF_8)); expectedBuffer = BufferUtil.toDetailString(byteBuffer); - endpointFunctions.onBinary(byteBuffer, true); + endpointFunctions.onBinary(new BinaryFrame().setPayload(byteBuffer).setFin(true), new FrameCallback.Adapter()); socket.assertEvent(String.format(expectedEventFormat, args)); } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextStreamTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextStreamTest.java index 6521a09ccde..40ce5aaf6c1 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextStreamTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextStreamTest.java @@ -21,7 +21,6 @@ package org.eclipse.jetty.websocket.jsr356.function; import java.io.IOException; import java.io.Reader; import java.net.URI; -import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.function.Function; @@ -31,9 +30,10 @@ import javax.websocket.ClientEndpointConfig; import javax.websocket.EndpointConfig; import javax.websocket.OnMessage; -import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.function.EndpointFunctions; import org.eclipse.jetty.websocket.common.test.DummyConnection; import org.eclipse.jetty.websocket.jsr356.ClientContainer; @@ -130,7 +130,7 @@ public class JsrEndpointFunctions_OnMessage_TextStreamTest { TrackingSocket socket = performOnMessageInvocation(new MessageStreamSocket(), (endpoint) -> { - endpoint.onText(BufferUtil.toBuffer("Hello World", StandardCharsets.UTF_8), true); + endpoint.onText(new TextFrame().setPayload("Hello World").setFin(true), new FrameCallback.Adapter()); return null; }); socket.assertEvent("onMessage(MessageReader) = \"Hello World\""); diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextTest.java index 1ba28275876..ae02f15dcb9 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextTest.java @@ -33,8 +33,10 @@ import javax.websocket.OnMessage; import javax.websocket.Session; import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.InvalidSignatureException; +import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.DummyConnection; import org.eclipse.jetty.websocket.jsr356.ClientContainer; import org.eclipse.jetty.websocket.jsr356.ConfiguredEndpoint; @@ -101,7 +103,7 @@ public class JsrEndpointFunctions_OnMessage_TextTest endpointFunctions.onOpen(newSession(socket)); ByteBuffer payload = BufferUtil.toBuffer(msg, StandardCharsets.UTF_8); - endpointFunctions.onText(payload, true); + endpointFunctions.onText(new TextFrame().setPayload(payload).setFin(true), new FrameCallback.Adapter()); } private void assertOnMessageInvocation(TrackingSocket socket, String expectedEventFormat, Object... args) throws Exception diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerEndpointFunctions_OnMessage_TextStreamTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerEndpointFunctions_OnMessage_TextStreamTest.java index 55f15f42464..7baa0b65f4b 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerEndpointFunctions_OnMessage_TextStreamTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerEndpointFunctions_OnMessage_TextStreamTest.java @@ -21,7 +21,6 @@ package org.eclipse.jetty.websocket.jsr356.server; import java.io.IOException; import java.io.Reader; import java.net.URI; -import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.function.Function; @@ -32,9 +31,10 @@ import javax.websocket.OnMessage; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; -import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.function.EndpointFunctions; import org.eclipse.jetty.websocket.common.test.DummyConnection; import org.eclipse.jetty.websocket.jsr356.ClientContainer; @@ -131,7 +131,7 @@ public class JsrServerEndpointFunctions_OnMessage_TextStreamTest { TrackingSocket socket = performOnMessageInvocation(new MessageStreamSocket(), (endpoint) -> { - endpoint.onText(BufferUtil.toBuffer("Hello World", StandardCharsets.UTF_8), true); + endpoint.onText(new TextFrame().setPayload("Hello World").setFin(true), new FrameCallback.Adapter()); return null; }); socket.assertEvent("onMessage(MessageReader) = \"Hello World\""); @@ -161,7 +161,7 @@ public class JsrServerEndpointFunctions_OnMessage_TextStreamTest { TrackingSocket socket = performOnMessageInvocation(new MessageStreamParamSocket(), (endpoint) -> { - endpoint.onText(BufferUtil.toBuffer("Hello World", StandardCharsets.UTF_8), true); + endpoint.onText(new TextFrame().setPayload("Hello World").setFin(true), new FrameCallback.Adapter()); return null; }); socket.assertEvent("onMessage(MessageReader,foo) = \"Hello World\""); diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/FrameCallback.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/FrameCallback.java new file mode 100644 index 00000000000..b45d2e6b748 --- /dev/null +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/FrameCallback.java @@ -0,0 +1,53 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.api; + +public interface FrameCallback +{ + /** + *

+ * Callback invoked when the frame fails. + *

+ * + * @param cause the reason for the frame failure + */ + void fail(Throwable cause); + + /** + *

+ * Callback invoked when the frame read/write completes. + *

+ * + * @see #fail(Throwable) + */ + void succeed(); + + class Adapter implements FrameCallback + { + @Override + public void fail(Throwable cause) + { + } + + @Override + public void succeed() + { + } + } +} diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/Session.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/Session.java index f96c70f80ea..5566fe0d19d 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/Session.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/Session.java @@ -107,7 +107,7 @@ public interface Session extends Closeable * * @return the local side address */ - public InetSocketAddress getLocalAddress(); + InetSocketAddress getLocalAddress(); /** * Access the (now read-only) {@link WebSocketPolicy} in use for this connection. @@ -136,7 +136,7 @@ public interface Session extends Closeable * * @return the remote side address */ - public InetSocketAddress getRemoteAddress(); + InetSocketAddress getRemoteAddress(); /** * Get the UpgradeRequest used to create this session @@ -157,7 +157,7 @@ public interface Session extends Closeable * * @return whether the session is open */ - abstract boolean isOpen(); + boolean isOpen(); /** * Return true if and only if the underlying socket is using a secure transport. diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java index b8063a04c76..cada57bf246 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java @@ -59,6 +59,9 @@ public class WebSocketPolicy * Default: 32768 (32 K) */ private int maxTextMessageBufferSize = 32 * KB; + + private int maxTextFramePayloadSize; // TODO + private int maxBinaryFramePayloadSize; // TODO /** * The maximum size of a binary message during parsing/generating. diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WriteCallback.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WriteCallback.java index 6bf685d081b..902b7adcc89 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WriteCallback.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/WriteCallback.java @@ -21,7 +21,7 @@ package org.eclipse.jetty.websocket.api; /** * Callback for Write events. */ -public interface WriteCallback +public interface WriteCallback extends FrameCallback { /* * NOTE: We don't expose org.eclipse.jetty.util.Callback here as that would complicate matters with the WebAppContext's classloader isolation. @@ -35,7 +35,7 @@ public interface WriteCallback * @param x * the reason for the write failure */ - public void writeFailed(Throwable x); + void writeFailed(Throwable x); /** *

@@ -44,5 +44,17 @@ public interface WriteCallback * * @see #writeFailed(Throwable) */ - public abstract void writeSuccess(); + void writeSuccess(); + + @Override + default void fail(Throwable cause) + { + writeFailed(cause); + } + + @Override + default void succeed() + { + writeSuccess(); + } } diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/IncomingFrames.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/IncomingFrames.java index 14ebbf63858..a8165f0370f 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/IncomingFrames.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/IncomingFrames.java @@ -18,12 +18,14 @@ package org.eclipse.jetty.websocket.api.extensions; +import org.eclipse.jetty.websocket.api.FrameCallback; + /** * Interface for dealing with Incoming Frames. */ public interface IncomingFrames { - public void incomingError(Throwable t); + void incomingError(Throwable t); /** * Process the incoming frame. @@ -34,5 +36,29 @@ public interface IncomingFrames * * @param frame the frame to process */ - public void incomingFrame(Frame frame); +// @Deprecated +// void incomingFrame(Frame frame); + + /** + * Process the incoming frame. + *

+ * Note: if you need to hang onto any information from the frame, be sure + * to copy it, as the information contained in the Frame will be released + * and/or reused by the implementation. + * + * @param frame the frame to process + * @param callback the read completion + */ + default void incomingFrame(Frame frame, FrameCallback callback) + { + try + { + //xincomingFrame(frame); + callback.succeed(); + } + catch (Throwable e) + { + callback.fail(e); + } + } } diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/OutgoingFrames.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/OutgoingFrames.java index 3a49ec8a591..51275990cf8 100644 --- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/OutgoingFrames.java +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/extensions/OutgoingFrames.java @@ -19,7 +19,7 @@ package org.eclipse.jetty.websocket.api.extensions; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; /** * Interface for dealing with frames outgoing to (eventually) the network layer. @@ -39,6 +39,5 @@ public interface OutgoingFrames * @param callback the callback to notify when the frame is written. * @param batchMode the batch mode requested by the sender. */ - void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode); - + void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode); } diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketUpgradeRequest.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketUpgradeRequest.java index de57588898e..29983d1750e 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketUpgradeRequest.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketUpgradeRequest.java @@ -564,20 +564,7 @@ public class WebSocketUpgradeRequest extends HttpRequest implements CompleteList { throw new HttpResponseException("Invalid Sec-WebSocket-Accept hash",response); } - - // We can upgrade - EndPoint endp = oldConn.getEndPoint(); - - WebSocketClientConnection connection = new WebSocketClientConnection(endp,wsClient.getExecutor(),wsClient.getScheduler(),localEndpoint.getPolicy(), - wsClient.getBufferPool()); - - URI requestURI = this.getURI(); - - WebSocketSession session = getSessionFactory().createSession(requestURI,localEndpoint,connection); - session.setUpgradeRequest(new ClientUpgradeRequest(this)); - session.setUpgradeResponse(new ClientUpgradeResponse(response)); - connection.addListener(session); - + ExtensionStack extensionStack = new ExtensionStack(getExtensionFactory()); List extensions = new ArrayList<>(); HttpField extField = response.getHeaders().getField(HttpHeader.SEC_WEBSOCKET_EXTENSIONS); @@ -597,12 +584,21 @@ public class WebSocketUpgradeRequest extends HttpRequest implements CompleteList } } extensionStack.negotiate(extensions); + + // We can upgrade + EndPoint endp = oldConn.getEndPoint(); - extensionStack.configure(connection.getParser()); - extensionStack.configure(connection.getGenerator()); + WebSocketClientConnection connection = new WebSocketClientConnection(endp,wsClient.getExecutor(),wsClient.getScheduler(),wsClient.getPolicy(), + wsClient.getBufferPool(), extensionStack); + + URI requestURI = this.getURI(); + + WebSocketSession session = getSessionFactory().createSession(requestURI,localEndpoint,connection); + session.setUpgradeRequest(new ClientUpgradeRequest(this)); + session.setUpgradeResponse(new ClientUpgradeResponse(response)); + connection.addListener(session); // Setup Incoming Routing - connection.setNextIncomingFrames(extensionStack); extensionStack.setNextIncoming(session); // Setup Outgoing Routing diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientConnection.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientConnection.java index 79069f026c7..59a05047c56 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientConnection.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientConnection.java @@ -25,13 +25,13 @@ import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.client.masks.Masker; import org.eclipse.jetty.websocket.client.masks.RandomMasker; import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.common.extensions.ExtensionStack; import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; /** @@ -41,9 +41,9 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection { private final Masker masker; - public WebSocketClientConnection(EndPoint endp, Executor executor, Scheduler scheduler, WebSocketPolicy websocketPolicy, ByteBufferPool bufferPool) + public WebSocketClientConnection(EndPoint endp, Executor executor, Scheduler scheduler, WebSocketPolicy websocketPolicy, ByteBufferPool bufferPool, ExtensionStack extensionStack) { - super(endp,executor,scheduler,websocketPolicy,bufferPool); + super(endp,executor,scheduler,websocketPolicy,bufferPool, extensionStack); this.masker = new RandomMasker(); } @@ -63,7 +63,7 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection * Override to set the masker. */ @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { if (frame instanceof WebSocketFrame) { @@ -71,10 +71,4 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection } super.outgoingFrame(frame,callback, batchMode); } - - @Override - public void setNextIncomingFrames(IncomingFrames incoming) - { - getParser().setIncomingFramesHandler(incoming); - } } diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientConnectTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientConnectTest.java index b0a4201be24..451d90001b6 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientConnectTest.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientConnectTest.java @@ -451,11 +451,16 @@ public class ClientConnectTest } catch (ExecutionException e) { - assertExpectedError(e, wsocket, - anyOf( - instanceOf(UpgradeException.class), - instanceOf(SocketTimeoutException.class), - instanceOf(ConnectException.class))); + if (OS.IS_WINDOWS) + { + // On windows, this is a SocketTimeoutException + assertExpectedError(e, wsocket, SocketTimeoutException.class); + } + else + { + // Expected path - java.net.ConnectException + assertExpectedError(e, wsocket, ConnectException.class); + } } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/BlockingWriteCallback.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/BlockingWriteCallback.java index 47322544ae0..c364951de82 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/BlockingWriteCallback.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/BlockingWriteCallback.java @@ -22,7 +22,7 @@ import java.io.IOException; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.SharedBlockingCallback; -import org.eclipse.jetty.util.thread.Invocable.InvocationType; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WriteCallback; /** @@ -39,7 +39,7 @@ public class BlockingWriteCallback extends SharedBlockingCallback return new WriteBlocker(acquire()); } - public static class WriteBlocker implements WriteCallback, Callback, AutoCloseable + public static class WriteBlocker implements FrameCallback, Callback, AutoCloseable { private final Blocker blocker; @@ -54,15 +54,15 @@ public class BlockingWriteCallback extends SharedBlockingCallback // The callback does not block, only the writer blocks return InvocationType.NON_BLOCKING; } - + @Override - public void writeFailed(Throwable x) + public void fail(Throwable cause) { - blocker.failed(x); + blocker.failed(cause); } - + @Override - public void writeSuccess() + public void succeed() { blocker.succeeded(); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java index 8c953507332..af70c1183c9 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java @@ -24,7 +24,6 @@ import java.util.concurrent.Executor; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.websocket.api.SuspendToken; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.io.IOState; @@ -38,7 +37,7 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken * @see org.eclipse.jetty.websocket.api.StatusCode * @see #close(int, String) */ - public void close(); + void close(); /** * Send a websocket Close frame, with status code. @@ -51,7 +50,7 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken * the (optional) reason. (can be null for no reason) * @see org.eclipse.jetty.websocket.api.StatusCode */ - public void close(int statusCode, String reason); + void close(int statusCode, String reason); /** * Terminate the connection (no close frame sent) @@ -75,7 +74,7 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken * * @return the idle timeout in milliseconds */ - public long getIdleTimeout(); + long getIdleTimeout(); /** * Get the IOState of the connection. @@ -120,7 +119,7 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken * * @return true if connection is open */ - public boolean isOpen(); + boolean isOpen(); /** * Tests if the connection is actively reading. @@ -140,16 +139,6 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken */ void setMaxIdleTimeout(long ms); - /** - * Set where the connection should send the incoming frames to. - *

- * Often this is from the Parser to the start of the extension stack, and eventually on to the session. - * - * @param incoming - * the incoming frames handler - */ - void setNextIncomingFrames(IncomingFrames incoming); - /** * Suspend a the incoming read events on the connection. * @return the suspend token @@ -160,5 +149,5 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken * Get Unique ID for the Connection * @return the unique ID for the connection */ - public String getId(); + String getId(); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java index e2281b6ec95..e204d86e91e 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java @@ -32,7 +32,6 @@ import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.frames.BinaryFrame; import org.eclipse.jetty.websocket.common.frames.CloseFrame; import org.eclipse.jetty.websocket.common.frames.ContinuationFrame; @@ -48,6 +47,11 @@ import org.eclipse.jetty.websocket.common.io.payload.PayloadProcessor; */ public class Parser { + public interface Handler + { + void onFrame(Frame frame); + } + private enum State { START, @@ -61,6 +65,7 @@ public class Parser private static final Logger LOG = Log.getLogger(Parser.class); private final WebSocketPolicy policy; private final ByteBufferPool bufferPool; + private final Parser.Handler parserHandler; // State specific private State state = State.START; @@ -86,14 +91,13 @@ public class Parser */ private byte flagsInUse=0x00; - private IncomingFrames incomingFramesHandler; - - public Parser(WebSocketPolicy wspolicy, ByteBufferPool bufferPool) + public Parser(WebSocketPolicy wspolicy, ByteBufferPool bufferPool, Parser.Handler parserHandler) { this.bufferPool = bufferPool; this.policy = wspolicy; + this.parserHandler = parserHandler; } - + private void assertSanePayloadLength(long len) { if (LOG.isDebugEnabled()) { @@ -124,9 +128,13 @@ public class Parser } break; case OpCode.TEXT: + // Quick failure for frames that already exceed messages size limits + // TODO: based on buffer limits policy.assertValidTextMessageSize((int)len); break; case OpCode.BINARY: + // Quick failure for frames that already exceed messages size limits + // TODO: based on buffer limits policy.assertValidBinaryMessageSize((int)len); break; } @@ -155,11 +163,6 @@ public class Parser } } - public IncomingFrames getIncomingFramesHandler() - { - return incomingFramesHandler; - } - public WebSocketPolicy getPolicy() { return policy; @@ -182,8 +185,6 @@ public class Parser protected void notifyFrame(final Frame f) { - if (LOG.isDebugEnabled()) - LOG.debug("{} Notify {}",policy.getBehavior(),getIncomingFramesHandler()); if (policy.getBehavior() == WebSocketBehavior.SERVER) { @@ -211,33 +212,7 @@ public class Parser } } - if (incomingFramesHandler == null) - { - return; - } - try - { - incomingFramesHandler.incomingFrame(f); - } - catch (WebSocketException e) - { - notifyWebSocketException(e); - } - catch (Throwable t) - { - LOG.warn(t); - notifyWebSocketException(new WebSocketException(t)); - } - } - - protected void notifyWebSocketException(WebSocketException e) - { - LOG.warn(e); - if (incomingFramesHandler == null) - { - return; - } - incomingFramesHandler.incomingError(e); + this.parserHandler.onFrame(f); } public void parse(ByteBuffer buffer) throws WebSocketException @@ -261,24 +236,19 @@ public class Parser reset(); } } - catch (WebSocketException e) - { - buffer.position(buffer.limit()); // consume remaining - reset(); - // let session know - notifyWebSocketException(e); - // need to throw for proper close behavior in connection - throw e; - } catch (Throwable t) { buffer.position(buffer.limit()); // consume remaining reset(); + // let session know - WebSocketException e = new WebSocketException(t); - notifyWebSocketException(e); - // need to throw for proper close behavior in connection - throw e; + WebSocketException wse; + if(t instanceof WebSocketException) + wse = (WebSocketException) t; + else + wse = new WebSocketException(t); + + throw wse; } } @@ -293,14 +263,10 @@ public class Parser /** * Parse the base framing protocol buffer. - *

- * Note the first byte (fin,rsv1,rsv2,rsv3,opcode) are parsed by the {@link Parser#parse(ByteBuffer)} method - *

- * Not overridable - * + * * @param buffer * the buffer to parse from. - * @return true if done parsing base framing protocol and ready for parsing of the payload. false if incomplete parsing of base framing protocol. + * @return true if done parsing a whole frame. false if incomplete/partial parsing of frame. */ private boolean parseFrame(ByteBuffer buffer) { @@ -650,30 +616,16 @@ public class Parser return false; } - public void setIncomingFramesHandler(IncomingFrames incoming) - { - this.incomingFramesHandler = incoming; - } - @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Parser@").append(Integer.toHexString(hashCode())); - builder.append("["); - if (incomingFramesHandler == null) - { - builder.append("NO_HANDLER"); - } - else - { - builder.append(incomingFramesHandler.getClass().getSimpleName()); - } + builder.append("[").append(policy.getBehavior()); builder.append(",s=").append(state); builder.append(",c=").append(cursor); builder.append(",len=").append(payloadLength); builder.append(",f=").append(frame); - // builder.append(",p=").append(policy); builder.append("]"); return builder.toString(); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketRemoteEndpoint.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketRemoteEndpoint.java index 9e399e9b797..b8508e081f1 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketRemoteEndpoint.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketRemoteEndpoint.java @@ -29,6 +29,7 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; @@ -299,7 +300,7 @@ public class WebSocketRemoteEndpoint implements RemoteEndpoint } } - public void uncheckedSendFrame(WebSocketFrame frame, WriteCallback callback) + public void uncheckedSendFrame(WebSocketFrame frame, FrameCallback callback) { try { @@ -311,7 +312,7 @@ public class WebSocketRemoteEndpoint implements RemoteEndpoint } catch (IOException e) { - callback.writeFailed(e); + callback.fail(e); } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java index de2b5e146bb..6247a2ab050 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java @@ -45,6 +45,7 @@ import org.eclipse.jetty.util.thread.ThreadClassLoaderScope; import org.eclipse.jetty.websocket.api.BatchMode; import org.eclipse.jetty.websocket.api.CloseException; import org.eclipse.jetty.websocket.api.CloseStatus; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.StatusCode; @@ -383,12 +384,12 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem // Forward Errors to User WebSocket Object endpointFunctions.onError(t); } - + /** - * Incoming Raw Frames from Parser + * Incoming Raw Frames from Parser (after ExtensionStack) */ @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { ClassLoader old = Thread.currentThread().getContextClassLoader(); try @@ -396,6 +397,8 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem Thread.currentThread().setContextClassLoader(classLoader); if (connection.getIOState().isInputAvailable()) { + // For endpoints that want to see raw frames. + // These are immutable. endpointFunctions.onFrame(frame); byte opcode = frame.getOpCode(); @@ -409,6 +412,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem // process handshake getConnection().getIOState().onCloseRemote(close); + callback.succeed(); return; } @@ -430,6 +434,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem } endpointFunctions.onPing(frame.getPayload()); + callback.succeed(); getRemote().sendPong(pongBuf); break; @@ -440,23 +445,24 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem LOG.debug("PONG: {}", BufferUtil.toDetailString(frame.getPayload())); endpointFunctions.onPong(frame.getPayload()); + callback.succeed(); break; } case OpCode.BINARY: { - endpointFunctions.onBinary(frame.getPayload(), frame.isFin()); + endpointFunctions.onBinary(frame, callback); return; } case OpCode.TEXT: { - endpointFunctions.onText(frame.getPayload(), frame.isFin()); + endpointFunctions.onText(frame, callback); return; } case OpCode.CONTINUATION: { - endpointFunctions.onContinuation(frame.getPayload(), frame.isFin()); + endpointFunctions.onContinuation(frame, callback); if (activeMessageSink != null) - activeMessageSink.accept(frame.getPayload(), frame.isFin()); + activeMessageSink.accept(frame, callback); return; } @@ -475,6 +481,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem } catch (NotUtf8Exception e) { + callback.fail(e); notifyError(e); close(StatusCode.BAD_PAYLOAD, e.getMessage()); } @@ -487,9 +494,11 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem Throwable cause = getInvokedCause(t); LOG.warn("Unhandled Error (closing connection)", cause); - + + callback.fail(cause); + notifyError(cause); - + // Unhandled Error, close the connection. switch (getPolicy().getBehavior()) { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java index cd2e0aa5136..598d6eeb1a9 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/AbstractExtension.java @@ -29,8 +29,8 @@ import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; @@ -176,13 +176,13 @@ public abstract class AbstractExtension extends AbstractLifeCycle implements Dum this.nextIncoming.incomingError(e); } - protected void nextIncomingFrame(Frame frame) + protected void nextIncomingFrame(Frame frame, FrameCallback callback) { log.debug("nextIncomingFrame({})",frame); - this.nextIncoming.incomingFrame(frame); + this.nextIncoming.incomingFrame(frame, callback); } - protected void nextOutgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + protected void nextOutgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { log.debug("nextOutgoingFrame({})",frame); this.nextOutgoing.outgoingFrame(frame,callback, batchMode); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java index 92b6fa60e8e..12b6b1e683c 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java @@ -33,8 +33,8 @@ import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; @@ -215,9 +215,9 @@ public class ExtensionStack extends ContainerLifeCycle implements IncomingFrames } @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { - nextIncoming.incomingFrame(frame); + nextIncoming.incomingFrame(frame, callback); } /** @@ -287,7 +287,7 @@ public class ExtensionStack extends ContainerLifeCycle implements IncomingFrames } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { FrameEntry entry = new FrameEntry(frame,callback,batchMode); if (LOG.isDebugEnabled()) @@ -383,10 +383,10 @@ public class ExtensionStack extends ContainerLifeCycle implements IncomingFrames private static class FrameEntry { private final Frame frame; - private final WriteCallback callback; + private final FrameCallback callback; private final BatchMode batchMode; - private FrameEntry(Frame frame, WriteCallback callback, BatchMode batchMode) + private FrameEntry(Frame frame, FrameCallback callback, BatchMode batchMode) { this.frame = frame; this.callback = callback; @@ -400,7 +400,7 @@ public class ExtensionStack extends ContainerLifeCycle implements IncomingFrames } } - private class Flusher extends IteratingCallback implements WriteCallback + private class Flusher extends IteratingCallback implements FrameCallback { private FrameEntry current; @@ -433,34 +433,34 @@ public class ExtensionStack extends ContainerLifeCycle implements IncomingFrames // The callback are those provided by WriteCallback (implemented // below) and even in case of writeFailed() we call succeeded(). } - + @Override - public void writeSuccess() + public void succeed() { // Notify first then call succeeded(), otherwise // write callbacks may be invoked out of order. notifyCallbackSuccess(current.callback); succeeded(); } - + @Override - public void writeFailed(Throwable x) + public void fail(Throwable cause) { // Notify first, the call succeeded() to drain the queue. // We don't want to call failed(x) because that will put // this flusher into a final state that cannot be exited, // and the failure of a frame may not mean that the whole // connection is now invalid. - notifyCallbackFailure(current.callback,x); + notifyCallbackFailure(current.callback,cause); succeeded(); } - private void notifyCallbackSuccess(WriteCallback callback) + private void notifyCallbackSuccess(FrameCallback callback) { try { if (callback != null) - callback.writeSuccess(); + callback.succeed(); } catch (Throwable x) { @@ -468,12 +468,12 @@ public class ExtensionStack extends ContainerLifeCycle implements IncomingFrames } } - private void notifyCallbackFailure(WriteCallback callback, Throwable failure) + private void notifyCallbackFailure(FrameCallback callback, Throwable failure) { try { if (callback != null) - callback.writeFailed(failure); + callback.fail(failure); } catch (Throwable x) { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/FrameCaptureExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/FrameCaptureExtension.java index ea962868382..97b57edfdf5 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/FrameCaptureExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/FrameCaptureExtension.java @@ -34,6 +34,7 @@ import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; @@ -65,12 +66,12 @@ public class FrameCaptureExtension extends AbstractExtension } @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { saveFrame(frame,false); try { - nextIncomingFrame(frame); + nextIncomingFrame(frame, callback); } catch (Throwable t) { @@ -81,7 +82,7 @@ public class FrameCaptureExtension extends AbstractExtension } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { saveFrame(frame,true); try diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java index 3ed6848ddf0..529dce5d768 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java @@ -33,7 +33,7 @@ import org.eclipse.jetty.util.IteratingCallback; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; @@ -127,7 +127,7 @@ public abstract class CompressExtension extends AbstractExtension */ abstract int getRsvUseMode(); - protected void forwardIncoming(Frame frame, ByteAccumulator accumulator) + protected void forwardIncoming(Frame frame, FrameCallback callback, ByteAccumulator accumulator) { DataFrame newFrame = new DataFrame(frame); // Unset RSV1 since it's not compressed anymore. @@ -139,7 +139,7 @@ public abstract class CompressExtension extends AbstractExtension BufferUtil.flipToFill(buffer); accumulator.transferTo(buffer); newFrame.setPayload(buffer); - nextIncomingFrame(newFrame); + nextIncomingFrame(newFrame, callback); } finally { @@ -199,7 +199,7 @@ public abstract class CompressExtension extends AbstractExtension } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { // We use a queue and an IteratingCallback to handle concurrency. // We must compress and write atomically, otherwise the compression @@ -234,12 +234,12 @@ public abstract class CompressExtension extends AbstractExtension } } - protected void notifyCallbackSuccess(WriteCallback callback) + protected void notifyCallbackSuccess(FrameCallback callback) { try { if (callback != null) - callback.writeSuccess(); + callback.succeed(); } catch (Throwable x) { @@ -248,12 +248,12 @@ public abstract class CompressExtension extends AbstractExtension } } - protected void notifyCallbackFailure(WriteCallback callback, Throwable failure) + protected void notifyCallbackFailure(FrameCallback callback, Throwable failure) { try { if (callback != null) - callback.writeFailed(failure); + callback.fail(failure); } catch (Throwable x) { @@ -390,10 +390,10 @@ public abstract class CompressExtension extends AbstractExtension private static class FrameEntry { private final Frame frame; - private final WriteCallback callback; + private final FrameCallback callback; private final BatchMode batchMode; - private FrameEntry(Frame frame, WriteCallback callback, BatchMode batchMode) + private FrameEntry(Frame frame, FrameCallback callback, BatchMode batchMode) { this.frame = frame; this.callback = callback; @@ -407,7 +407,7 @@ public abstract class CompressExtension extends AbstractExtension } } - private class Flusher extends IteratingCallback implements WriteCallback + private class Flusher extends IteratingCallback implements FrameCallback { private FrameEntry current; private boolean finished = true; @@ -564,22 +564,22 @@ public abstract class CompressExtension extends AbstractExtension while ((entry = pollEntry()) != null) notifyCallbackFailure(entry.callback,x); } - + @Override - public void writeSuccess() + public void succeed() { if (finished) notifyCallbackSuccess(current.callback); succeeded(); } - + @Override - public void writeFailed(Throwable x) + public void fail(Throwable cause) { - notifyCallbackFailure(current.callback,x); + notifyCallbackFailure(current.callback,cause); // If something went wrong, very likely the compression context // will be invalid, so we need to fail this IteratingCallback. - failed(x); + failed(cause); } } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DeflateFrameExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DeflateFrameExtension.java index 234900fe1a7..4fb88314e03 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DeflateFrameExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/DeflateFrameExtension.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.common.extensions.compress; import java.util.zip.DataFormatException; import org.eclipse.jetty.websocket.api.BadPayloadException; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; /** @@ -49,7 +50,7 @@ public class DeflateFrameExtension extends CompressExtension } @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { // Incoming frames are always non concurrent because // they are read and parsed with a single thread, and @@ -57,7 +58,7 @@ public class DeflateFrameExtension extends CompressExtension if ( frame.getType().isControl() || !frame.isRsv1() || !frame.hasPayload() ) { - nextIncomingFrame(frame); + nextIncomingFrame(frame, callback); return; } @@ -66,7 +67,7 @@ public class DeflateFrameExtension extends CompressExtension ByteAccumulator accumulator = newByteAccumulator(); decompress(accumulator, frame.getPayload()); decompress(accumulator, TAIL_BYTES_BUF.slice()); - forwardIncoming(frame, accumulator); + forwardIncoming(frame, callback, accumulator); } catch (DataFormatException e) { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java index ade66b6df95..a190f2c38ae 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java @@ -25,7 +25,7 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BadPayloadException; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.OpCode; @@ -52,7 +52,7 @@ public class PerMessageDeflateExtension extends CompressExtension } @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { // Incoming frames are always non concurrent because // they are read and parsed with a single thread, and @@ -67,7 +67,7 @@ public class PerMessageDeflateExtension extends CompressExtension if (OpCode.isControlFrame(frame.getOpCode()) || !incomingCompressed) { - nextIncomingFrame(frame); + nextIncomingFrame(frame, callback); return; } @@ -82,7 +82,7 @@ public class PerMessageDeflateExtension extends CompressExtension decompress(accumulator, TAIL_BYTES_BUF.slice()); } - forwardIncoming(frame, accumulator); + forwardIncoming(frame, callback, accumulator); } catch (DataFormatException e) { @@ -94,7 +94,7 @@ public class PerMessageDeflateExtension extends CompressExtension } @Override - protected void nextIncomingFrame(Frame frame) + protected void nextIncomingFrame(Frame frame, FrameCallback callback) { if (frame.isFin() && !incomingContextTakeover) { @@ -102,11 +102,11 @@ public class PerMessageDeflateExtension extends CompressExtension decompressCount.set(0); getInflater().reset(); } - super.nextIncomingFrame(frame); + super.nextIncomingFrame(frame, callback); } @Override - protected void nextOutgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + protected void nextOutgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { if (frame.isFin() && !outgoingContextTakeover) { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java index b297ccfd73a..fe2aa8e0e1f 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java @@ -27,7 +27,7 @@ import org.eclipse.jetty.util.IteratingCallback; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.OpCode; @@ -52,13 +52,13 @@ public class FragmentExtension extends AbstractExtension } @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { - nextIncomingFrame(frame); + nextIncomingFrame(frame, callback); } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { ByteBuffer payload = frame.getPayload(); int length = payload != null ? payload.remaining() : 0; @@ -101,10 +101,10 @@ public class FragmentExtension extends AbstractExtension private static class FrameEntry { private final Frame frame; - private final WriteCallback callback; + private final FrameCallback callback; private final BatchMode batchMode; - private FrameEntry(Frame frame, WriteCallback callback, BatchMode batchMode) + private FrameEntry(Frame frame, FrameCallback callback, BatchMode batchMode) { this.frame = frame; this.callback = callback; @@ -118,7 +118,7 @@ public class FragmentExtension extends AbstractExtension } } - private class Flusher extends IteratingCallback implements WriteCallback + private class Flusher extends IteratingCallback implements FrameCallback { private FrameEntry current; private boolean finished = true; @@ -180,34 +180,34 @@ public class FragmentExtension extends AbstractExtension // The callback are those provided by WriteCallback (implemented // below) and even in case of writeFailed() we call succeeded(). } - + @Override - public void writeSuccess() + public void succeed() { // Notify first then call succeeded(), otherwise // write callbacks may be invoked out of order. notifyCallbackSuccess(current.callback); succeeded(); } - + @Override - public void writeFailed(Throwable x) + public void fail(Throwable cause) { // Notify first, the call succeeded() to drain the queue. // We don't want to call failed(x) because that will put // this flusher into a final state that cannot be exited, // and the failure of a frame may not mean that the whole // connection is now invalid. - notifyCallbackFailure(current.callback, x); + notifyCallbackFailure(current.callback, cause); succeeded(); } - private void notifyCallbackSuccess(WriteCallback callback) + private void notifyCallbackSuccess(FrameCallback callback) { try { if (callback != null) - callback.writeSuccess(); + callback.succeed(); } catch (Throwable x) { @@ -216,12 +216,12 @@ public class FragmentExtension extends AbstractExtension } } - private void notifyCallbackFailure(WriteCallback callback, Throwable failure) + private void notifyCallbackFailure(FrameCallback callback, Throwable failure) { try { if (callback != null) - callback.writeFailed(failure); + callback.fail(failure); } catch (Throwable x) { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/identity/IdentityExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/identity/IdentityExtension.java index f8ec1260fcc..4d222bb036e 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/identity/IdentityExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/identity/IdentityExtension.java @@ -21,7 +21,7 @@ package org.eclipse.jetty.websocket.common.extensions.identity; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; @@ -50,14 +50,14 @@ public class IdentityExtension extends AbstractExtension } @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { // pass through - nextIncomingFrame(frame); + nextIncomingFrame(frame, callback); } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { // pass through nextOutgoingFrame(frame,callback, batchMode); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctions.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctions.java index d38dd5f363e..afbe89e553c 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctions.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctions.java @@ -34,6 +34,7 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.InvalidWebSocketException; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketConnectionListener; @@ -702,42 +703,42 @@ public class CommonEndpointFunctions extends AbstractLifeCycl } @Override - public void onText(ByteBuffer payload, boolean fin) + public void onText(Frame frame, FrameCallback callback) { assertIsStarted(); if (activeMessageSink == null) activeMessageSink = onTextSink; - acceptMessage(payload, fin); + acceptMessage(frame, callback); } @Override - public void onBinary(ByteBuffer payload, boolean fin) + public void onBinary(Frame frame, FrameCallback callback) { assertIsStarted(); if (activeMessageSink == null) activeMessageSink = onBinarySink; - acceptMessage(payload, fin); + acceptMessage(frame, callback); } @Override - public void onContinuation(ByteBuffer payload, boolean fin) + public void onContinuation(Frame frame, FrameCallback callback) { - acceptMessage(payload, fin); + acceptMessage(frame, callback); } - private void acceptMessage(ByteBuffer payload, boolean fin) + private void acceptMessage(Frame frame, FrameCallback callback) { // No message sink is active if (activeMessageSink == null) return; // Accept the payload into the message sink - activeMessageSink.accept(payload, fin); - if (fin) + activeMessageSink.accept(frame, callback); + if (frame.isFin()) activeMessageSink = null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/EndpointFunctions.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/EndpointFunctions.java index 41607b94de4..28bc2a1dbfe 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/EndpointFunctions.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/EndpointFunctions.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.common.function; import java.nio.ByteBuffer; import org.eclipse.jetty.util.component.LifeCycle; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.CloseInfo; @@ -39,11 +40,11 @@ public interface EndpointFunctions extends LifeCycle void onError(Throwable cause); - void onText(ByteBuffer payload, boolean fin); + void onText(Frame frame, FrameCallback callback); - void onBinary(ByteBuffer payload, boolean fin); + void onBinary(Frame frame, FrameCallback callback); - void onContinuation(ByteBuffer payload, boolean fin); + void onContinuation(Frame frame, FrameCallback callback); void onPing(ByteBuffer payload); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java index cb5a6f939bd..eacc5518ab0 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java @@ -42,6 +42,7 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.websocket.api.BatchMode; import org.eclipse.jetty.websocket.api.CloseException; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.SuspendToken; import org.eclipse.jetty.websocket.api.WebSocketBehavior; @@ -54,15 +55,16 @@ import org.eclipse.jetty.websocket.common.ConnectionState; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.LogicalConnection; import org.eclipse.jetty.websocket.common.Parser; +import org.eclipse.jetty.websocket.common.extensions.ExtensionStack; import org.eclipse.jetty.websocket.common.io.IOState.ConnectionStateListener; /** * Provides the implementation of {@link LogicalConnection} within the framework of the new {@link org.eclipse.jetty.io.Connection} framework of {@code jetty-io}. */ -public abstract class AbstractWebSocketConnection extends AbstractConnection implements LogicalConnection, Connection.UpgradeTo, ConnectionStateListener, Dumpable +public abstract class AbstractWebSocketConnection extends AbstractConnection implements LogicalConnection, Connection.UpgradeTo, ConnectionStateListener, Dumpable, Parser.Handler { private final AtomicBoolean closed = new AtomicBoolean(); - + private class Flusher extends FrameFlusher { private Flusher(ByteBufferPool bufferPool, int bufferSize, Generator generator, EndPoint endpoint) @@ -219,14 +221,15 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp private final AtomicBoolean suspendToken; private final FrameFlusher flusher; private final String id; + private final ExtensionStack extensionStack; private List extensions; private boolean isFilling; private ByteBuffer prefillBuffer; private ReadMode readMode = ReadMode.PARSE; private IOState ioState; private Stats stats = new Stats(); - - public AbstractWebSocketConnection(EndPoint endp, Executor executor, Scheduler scheduler, WebSocketPolicy policy, ByteBufferPool bufferPool) + + public AbstractWebSocketConnection(EndPoint endp, Executor executor, Scheduler scheduler, WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack) { super(endp,executor); this.id = String.format("%s:%d->%s:%d", @@ -237,8 +240,10 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp this.policy = policy; this.behavior = policy.getBehavior(); this.bufferPool = bufferPool; + this.extensionStack = extensionStack; + this.generator = new Generator(policy,bufferPool); - this.parser = new Parser(policy,bufferPool); + this.parser = new Parser(policy,bufferPool,this); this.scheduler = scheduler; this.extensions = new ArrayList<>(); this.suspendToken = new AtomicBoolean(false); @@ -247,6 +252,10 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp this.flusher = new Flusher(bufferPool,policy.getMaxBinaryMessageBufferSize(),generator,endp); this.setInputBufferSize(policy.getInputBufferSize()); this.setMaxIdleTimeout(policy.getIdleTimeout()); + + this.extensionStack.setPolicy(this.policy); + this.extensionStack.configure(this.parser); + this.extensionStack.configure(this.generator); } @Override @@ -494,7 +503,26 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp break; } } - + + @Override + public void onFrame(Frame frame) + { + extensionStack.incomingFrame(frame, new FrameCallback() + { + @Override + public void fail(Throwable cause) + { + // TODO: suspend + } + + @Override + public void succeed() + { + // TODO: resume + } + }); + } + @Override public void onFillable() { @@ -557,7 +585,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp private void notifyError(Throwable t) { - getParser().getIncomingFramesHandler().incomingError(t); + extensionStack.incomingError(t); } @Override @@ -606,7 +634,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp * Frame from API, User, or Internal implementation destined for network. */ @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { if (LOG.isDebugEnabled()) { @@ -678,6 +706,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp { LOG.debug("Filled {} bytes - {}",filled,BufferUtil.toDetailString(buffer)); } + parser.parse(buffer); } } @@ -697,7 +726,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp { LOG.warn(t); close(StatusCode.ABNORMAL,t.getMessage()); - // TODO: should probably only switch to discard if a non-ws-endpoint error + // TODO: should ws only switch to discard if a non-ws-endpoint error? return ReadMode.DISCARD; } } @@ -745,7 +774,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp getEndPoint().setIdleTimeout(ms); } } - + @Override public SuspendToken suspend() { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java index aca26826cbf..13995320851 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java @@ -34,7 +34,7 @@ import org.eclipse.jetty.util.IteratingCallback; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.OpCode; @@ -249,11 +249,11 @@ public class FrameFlusher private class FrameEntry { private final Frame frame; - private final WriteCallback callback; + private final FrameCallback callback; private final BatchMode batchMode; private ByteBuffer headerBuffer; - private FrameEntry(Frame frame, WriteCallback callback, BatchMode batchMode) + private FrameEntry(Frame frame, FrameCallback callback, BatchMode batchMode) { this.frame = Objects.requireNonNull(frame); this.callback = callback; @@ -332,7 +332,7 @@ public class FrameFlusher } } - public void enqueue(Frame frame, WriteCallback callback, BatchMode batchMode) + public void enqueue(Frame frame, FrameCallback callback, BatchMode batchMode) { if (closed.get()) { @@ -382,13 +382,13 @@ public class FrameFlusher flusher.iterate(); } - protected void notifyCallbackFailure(WriteCallback callback, Throwable failure) + protected void notifyCallbackFailure(FrameCallback callback, Throwable failure) { try { if (callback != null) { - callback.writeFailed(failure); + callback.fail(failure); } } catch (Throwable x) @@ -398,13 +398,13 @@ public class FrameFlusher } } - protected void notifyCallbackSuccess(WriteCallback callback) + protected void notifyCallbackSuccess(FrameCallback callback) { try { if (callback != null) { - callback.writeSuccess(); + callback.succeed(); } } catch (Throwable x) diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FramePipes.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FramePipes.java index 35bf9b9e9cd..d4b122834fa 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FramePipes.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FramePipes.java @@ -19,7 +19,7 @@ package org.eclipse.jetty.websocket.common.io; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; @@ -42,9 +42,9 @@ public class FramePipes } @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { - this.outgoing.outgoingFrame(frame,null, BatchMode.OFF); + this.outgoing.outgoingFrame(frame, callback, BatchMode.OFF); } } @@ -58,17 +58,9 @@ public class FramePipes } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { - try - { - this.incoming.incomingFrame(frame); - callback.writeSuccess(); - } - catch (Throwable t) - { - callback.writeFailed(t); - } + this.incoming.incomingFrame(frame, callback); } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ByteArrayMessageSink.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ByteArrayMessageSink.java index e7ec840bd3b..6a13e9a74ab 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ByteArrayMessageSink.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ByteArrayMessageSink.java @@ -19,12 +19,13 @@ package org.eclipse.jetty.websocket.common.message; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.nio.ByteBuffer; import java.util.function.Function; import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; public class ByteArrayMessageSink implements MessageSink { @@ -42,12 +43,13 @@ public class ByteArrayMessageSink implements MessageSink } @Override - public void accept(ByteBuffer payload, Boolean fin) + public void accept(Frame frame, FrameCallback callback) { try { - if (payload != null) + if (frame.hasPayload()) { + ByteBuffer payload = frame.getPayload(); policy.assertValidBinaryMessageSize(size + payload.remaining()); size += payload.remaining(); @@ -56,19 +58,25 @@ public class ByteArrayMessageSink implements MessageSink BufferUtil.writeTo(payload, out); } - } - catch (IOException e) - { - throw new RuntimeException("Unable to append Binary Message", e); - } - finally - { - if (fin) + + if (frame.isFin()) { if (out != null) notifyOnMessage(out.toByteArray()); else notifyOnMessage(EMPTY_BUFFER); + } + + callback.succeed(); + } + catch (Throwable t) + { + callback.fail(t); + } + finally + { + if (frame.isFin()) + { // reset out = null; size = 0; @@ -76,7 +84,7 @@ public class ByteArrayMessageSink implements MessageSink } } - protected Object notifyOnMessage(byte buf[]) + private Object notifyOnMessage(byte buf[]) { return onMessageFunction.apply(buf); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/FrameCallbackBuffer.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/FrameCallbackBuffer.java new file mode 100644 index 00000000000..927e2461ff4 --- /dev/null +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/FrameCallbackBuffer.java @@ -0,0 +1,35 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.common.message; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.websocket.api.FrameCallback; + +public class FrameCallbackBuffer +{ + public ByteBuffer buffer; + public FrameCallback callback; + + public FrameCallbackBuffer(FrameCallback callback, ByteBuffer buffer) + { + this.callback = callback; + this.buffer = buffer; + } +} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/InputStreamMessageSink.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/InputStreamMessageSink.java index c2fc5b61f07..46ca6ed0d61 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/InputStreamMessageSink.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/InputStreamMessageSink.java @@ -19,7 +19,6 @@ package org.eclipse.jetty.websocket.common.message; import java.io.InputStream; -import java.nio.ByteBuffer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.function.Function; @@ -27,6 +26,8 @@ import java.util.function.Function; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.FrameCallback; +import org.eclipse.jetty.websocket.api.extensions.Frame; public class InputStreamMessageSink implements MessageSink { @@ -43,7 +44,7 @@ public class InputStreamMessageSink implements MessageSink } @Override - public void accept(ByteBuffer payload, Boolean fin) + public void accept(Frame frame, FrameCallback callback) { try { @@ -55,7 +56,7 @@ public class InputStreamMessageSink implements MessageSink first = true; } - stream.accept(payload,fin); + stream.accept(frame, callback); if (first) { dispatchCompleted = new CountDownLatch(1); @@ -83,7 +84,7 @@ public class InputStreamMessageSink implements MessageSink finally { //noinspection Duplicates - if (fin) + if (frame.isFin()) { if (LOG.isDebugEnabled()) LOG.debug("dispatch complete await() - {}", stream); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageInputStream.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageInputStream.java index 94009cd5432..90b07cb1c97 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageInputStream.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageInputStream.java @@ -27,12 +27,13 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.FrameCallback; +import org.eclipse.jetty.websocket.api.extensions.Frame; /** - * Support class for reading a (single) WebSocket BINARY message via a InputStream. + * Support class for reading a WebSocket BINARY message via a InputStream. *

* An InputStream that can access a queue of ByteBuffer payloads, along with expected InputStream blocking behavior. *

@@ -40,15 +41,15 @@ import org.eclipse.jetty.util.log.Logger; public class MessageInputStream extends InputStream implements MessageSink { private static final Logger LOG = Log.getLogger(MessageInputStream.class); - private static final ByteBuffer EOF = ByteBuffer.allocate(0).asReadOnlyBuffer(); + private static final FrameCallbackBuffer EOF = new FrameCallbackBuffer(new FrameCallback.Adapter(), ByteBuffer.allocate(0).asReadOnlyBuffer()); - private final BlockingDeque buffers = new LinkedBlockingDeque<>(); + private final BlockingDeque buffers = new LinkedBlockingDeque<>(); private final AtomicBoolean closed = new AtomicBoolean(false); private final long timeoutMs; private final CountDownLatch closedLatch = new CountDownLatch(1); - private ByteBuffer activeBuffer = null; + private FrameCallbackBuffer activeBuffer = null; public MessageInputStream() { @@ -61,16 +62,17 @@ public class MessageInputStream extends InputStream implements MessageSink } @Override - public void accept(ByteBuffer payload, Boolean fin) + public void accept(Frame frame, FrameCallback callback) { if (LOG.isDebugEnabled()) { - LOG.debug("Appending {} chunk: {}", fin ? "final" : "non-final", BufferUtil.toDetailString(payload)); + LOG.debug("Appending {}", frame); } // If closed, we should just toss incoming payloads into the bit bucket. if (closed.get()) { + callback.fail(new IOException("Already Closed")); return; } @@ -79,22 +81,29 @@ public class MessageInputStream extends InputStream implements MessageSink // be processed after this method returns. try { - if (payload == null) + if (!frame.hasPayload()) { // skip if no payload + callback.succeed(); return; } + + ByteBuffer payload = frame.getPayload(); int capacity = payload.remaining(); if (capacity <= 0) { // skip if no payload data to copy + callback.succeed(); return; } + // TODO: the copy buffer should be pooled too, but no buffer pool available from here. ByteBuffer copy = payload.isDirect() ? ByteBuffer.allocateDirect(capacity) : ByteBuffer.allocate(capacity); copy.put(payload).flip(); - buffers.put(copy); + buffers.put(new FrameCallbackBuffer(callback,copy)); + + // TODO: backpressure } catch (InterruptedException e) { @@ -102,7 +111,7 @@ public class MessageInputStream extends InputStream implements MessageSink } finally { - if (fin) + if (frame.isFin()) { buffers.offer(EOF); } @@ -145,13 +154,14 @@ public class MessageInputStream extends InputStream implements MessageSink } // grab a fresh buffer - while (activeBuffer == null || !activeBuffer.hasRemaining()) + while (activeBuffer == null || !activeBuffer.buffer.hasRemaining()) { if (LOG.isDebugEnabled()) LOG.debug("Waiting {} ms to read", timeoutMs); if (timeoutMs < 0) { // Wait forever until a buffer is available. + // TODO: notify connection to resume (if paused) activeBuffer = buffers.take(); } else @@ -177,7 +187,7 @@ public class MessageInputStream extends InputStream implements MessageSink } } - return activeBuffer.get() & 0xFF; + return activeBuffer.buffer.get() & 0xFF; } catch (InterruptedException x) { @@ -195,6 +205,8 @@ public class MessageInputStream extends InputStream implements MessageSink throw new IOException("reset() not supported"); } + // TODO: remove await! + @Deprecated public void awaitClose() { try diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageReader.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageReader.java index 1c3fe107679..3c2b01678de 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageReader.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageReader.java @@ -19,9 +19,11 @@ package org.eclipse.jetty.websocket.common.message; import java.io.InputStreamReader; -import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import org.eclipse.jetty.websocket.api.FrameCallback; +import org.eclipse.jetty.websocket.api.extensions.Frame; + /** * Support class for reading a (single) WebSocket TEXT message via a Reader. *

@@ -38,11 +40,13 @@ public class MessageReader extends InputStreamReader implements MessageSink } @Override - public void accept(ByteBuffer payload, Boolean fin) + public void accept(Frame frame, FrameCallback callback) { - this.stream.accept(payload, fin); + this.stream.accept(frame, callback); } - + + // TODO: remove await! + @Deprecated public void awaitClose() { stream.awaitClose(); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageSink.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageSink.java index 2d00bd3d6f8..7808f08c05f 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageSink.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageSink.java @@ -18,23 +18,22 @@ package org.eclipse.jetty.websocket.common.message; -import java.nio.ByteBuffer; -import java.util.function.BiConsumer; +import org.eclipse.jetty.websocket.api.FrameCallback; +import org.eclipse.jetty.websocket.api.extensions.Frame; /** * Sink consumer for messages (used for multiple frames with continuations, * and also to allow for streaming APIs) */ -public interface MessageSink extends BiConsumer +public interface MessageSink { /** * Consume the frame payload to the message. * - * @param payload - * the frame payload to append. - * @param fin - * flag indicating if this is the final part of the message or not. + * @param frame + * the frame, its payload (and fin state) to append + * @param callback + * the callback for how the frame was consumed */ - @Override - void accept(ByteBuffer payload, Boolean fin); + void accept(Frame frame, FrameCallback callback); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageWriter.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageWriter.java index 33e707fb39a..8d9f79e5f41 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageWriter.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageWriter.java @@ -27,6 +27,7 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.BlockingWriteCallback; @@ -50,7 +51,7 @@ public class MessageWriter extends Writer private TextFrame frame; private ByteBuffer buffer; private Utf8CharBuffer utf; - private WriteCallback callback; + private FrameCallback callback; private boolean closed; public MessageWriter(WebSocketSession session) @@ -199,27 +200,27 @@ public class MessageWriter extends Writer private void notifySuccess() { - WriteCallback callback; + FrameCallback callback; synchronized (this) { callback = this.callback; } if (callback != null) { - callback.writeSuccess(); + callback.succeed(); } } private void notifyFailure(Throwable failure) { - WriteCallback callback; + FrameCallback callback; synchronized (this) { callback = this.callback; } if (callback != null) { - callback.writeFailed(failure); + callback.fail(failure); } } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/PartialBinaryMessageSink.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/PartialBinaryMessageSink.java index 356c84481a7..1444767c5ce 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/PartialBinaryMessageSink.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/PartialBinaryMessageSink.java @@ -18,9 +18,11 @@ package org.eclipse.jetty.websocket.common.message; -import java.nio.ByteBuffer; import java.util.function.Function; +import org.eclipse.jetty.websocket.api.FrameCallback; +import org.eclipse.jetty.websocket.api.extensions.Frame; + public class PartialBinaryMessageSink implements MessageSink { private final Function onBinaryFunction; @@ -31,8 +33,16 @@ public class PartialBinaryMessageSink implements MessageSink } @Override - public void accept(ByteBuffer payload, Boolean fin) + public void accept(Frame frame, FrameCallback callback) { - onBinaryFunction.apply(new PartialBinaryMessage(payload,fin)); + try + { + onBinaryFunction.apply(new PartialBinaryMessage(frame.getPayload(), frame.isFin())); + callback.succeed(); + } + catch(Throwable t) + { + callback.fail(t); + } } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/PartialTextMessageSink.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/PartialTextMessageSink.java index fe3e4d05e0f..f646af877bb 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/PartialTextMessageSink.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/PartialTextMessageSink.java @@ -18,9 +18,10 @@ package org.eclipse.jetty.websocket.common.message; -import java.nio.ByteBuffer; import java.util.function.Function; +import org.eclipse.jetty.websocket.api.FrameCallback; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.util.Utf8PartialBuilder; public class PartialTextMessageSink implements MessageSink @@ -35,16 +36,21 @@ public class PartialTextMessageSink implements MessageSink } @Override - public void accept(ByteBuffer payload, Boolean fin) + public void accept(Frame frame, FrameCallback callback) { - String partialText = utf8Partial.toPartialString(payload); + String partialText = utf8Partial.toPartialString(frame.getPayload()); try { - onTextFunction.apply(new PartialTextMessage(partialText,fin)); + onTextFunction.apply(new PartialTextMessage(partialText,frame.isFin())); + callback.succeed(); + } + catch(Throwable t) + { + callback.fail(t); } finally { - if (fin) + if (frame.isFin()) utf8Partial.reset(); } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ReaderMessageSink.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ReaderMessageSink.java index 488429a04b7..245fa9edaa6 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ReaderMessageSink.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ReaderMessageSink.java @@ -19,7 +19,6 @@ package org.eclipse.jetty.websocket.common.message; import java.io.Reader; -import java.nio.ByteBuffer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.function.Function; @@ -27,6 +26,8 @@ import java.util.function.Function; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.FrameCallback; +import org.eclipse.jetty.websocket.api.extensions.Frame; public class ReaderMessageSink implements MessageSink { @@ -43,7 +44,7 @@ public class ReaderMessageSink implements MessageSink } @Override - public void accept(ByteBuffer payload, Boolean fin) + public void accept(Frame frame, FrameCallback callback) { try { @@ -55,7 +56,7 @@ public class ReaderMessageSink implements MessageSink first = true; } - stream.accept(payload, fin); + stream.accept(frame, callback); if (first) { dispatchCompleted = new CountDownLatch(1); @@ -84,7 +85,7 @@ public class ReaderMessageSink implements MessageSink finally { //noinspection Duplicates - if (fin) + if (frame.isFin()) { if (LOG.isDebugEnabled()) LOG.debug("dispatch complete await() - {}", stream); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/StringMessageSink.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/StringMessageSink.java index 33910f15040..778cfe9f206 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/StringMessageSink.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/StringMessageSink.java @@ -25,7 +25,9 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; public class StringMessageSink implements MessageSink { @@ -42,13 +44,14 @@ public class StringMessageSink implements MessageSink this.onMessageFunction = onMessageFunction; this.size = 0; } - + @SuppressWarnings("Duplicates") @Override - public void accept(ByteBuffer payload, Boolean fin) + public void accept(Frame frame, FrameCallback callback) { - if (payload != null) + if (frame.hasPayload()) { + ByteBuffer payload = frame.getPayload(); policy.assertValidTextMessageSize(size + payload.remaining()); size += payload.remaining(); @@ -62,13 +65,15 @@ public class StringMessageSink implements MessageSink utf.append(payload); } - if (fin) + if (frame.isFin()) { // notify event if (utf != null) onMessageFunction.apply(utf.toString()); else onMessageFunction.apply(""); + + callback.succeed(); // reset size = 0; utf = null; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ClosePayloadParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ClosePayloadParserTest.java index eed598e1ae1..58ef3917e9a 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ClosePayloadParserTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ClosePayloadParserTest.java @@ -53,9 +53,8 @@ public class ClosePayloadParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); parser.parse(buf); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/FrameCallbackAdapter.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/FrameCallbackAdapter.java new file mode 100644 index 00000000000..ce280b8dfda --- /dev/null +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/FrameCallbackAdapter.java @@ -0,0 +1,25 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.common; + +import org.eclipse.jetty.websocket.api.FrameCallback; + +public class FrameCallbackAdapter extends FrameCallback.Adapter +{ +} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorParserRoundtripTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorParserRoundtripTest.java index b8d915af057..b3caac2d3a4 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorParserRoundtripTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorParserRoundtripTest.java @@ -42,9 +42,8 @@ public class GeneratorParserRoundtripTest { WebSocketPolicy policy = WebSocketPolicy.newClientPolicy(); Generator gen = new Generator(policy,bufferPool); - Parser parser = new Parser(policy,bufferPool); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new Parser(policy,bufferPool,capture); String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"; @@ -80,9 +79,8 @@ public class GeneratorParserRoundtripTest public void testParserAndGeneratorMasked() throws Exception { Generator gen = new Generator(WebSocketPolicy.newClientPolicy(),bufferPool); - Parser parser = new Parser(WebSocketPolicy.newServerPolicy(),bufferPool); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new Parser(WebSocketPolicy.newServerPolicy(),bufferPool,capture); String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorTest.java index 46f76600b9e..af6ac3b814d 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorTest.java @@ -297,9 +297,8 @@ public class GeneratorTest // Parse complete buffer. WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); parser.parse(completeBuffer); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ParserTest.java index e0bcdeeaca3..4d6dbbbce93 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ParserTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ParserTest.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.List; import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; @@ -39,10 +40,15 @@ import org.eclipse.jetty.websocket.common.test.UnitGenerator; import org.eclipse.jetty.websocket.common.test.UnitParser; import org.eclipse.jetty.websocket.common.util.Hex; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class ParserTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + /** * Similar to the server side 5.15 testcase. A normal 2 fragment text text message, followed by another continuation. */ @@ -57,13 +63,12 @@ public class ParserTest send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); ByteBuffer completeBuf = UnitGenerator.generate(send); - UnitParser parser = new UnitParser(); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); - parser.parseQuietly(completeBuf); + expectedException.expect(ProtocolException.class); + parser.parse(completeBuf); - capture.assertErrorCount(1); capture.assertHasFrame(OpCode.TEXT,1); capture.assertHasFrame(OpCode.CONTINUATION,1); } @@ -80,12 +85,12 @@ public class ParserTest send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); ByteBuffer completeBuf = UnitGenerator.generate(send); - UnitParser parser = new UnitParser(); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); - parser.parseQuietly(completeBuf); + UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); + + expectedException.expect(ProtocolException.class); + parser.parse(completeBuf); - capture.assertErrorCount(1); capture.assertHasFrame(OpCode.TEXT,1); // fragment 1 } @@ -106,12 +111,10 @@ public class ParserTest send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); ByteBuffer completeBuf = UnitGenerator.generate(send); - UnitParser parser = new UnitParser(); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); - parser.parseQuietly(completeBuf); + UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); + parser.parse(completeBuf); - capture.assertErrorCount(0); capture.assertHasFrame(OpCode.TEXT,1); capture.assertHasFrame(OpCode.CONTINUATION,4); capture.assertHasFrame(OpCode.CLOSE,1); @@ -130,12 +133,10 @@ public class ParserTest send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); ByteBuffer completeBuf = UnitGenerator.generate(send); - UnitParser parser = new UnitParser(); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); parser.parse(completeBuf); - capture.assertErrorCount(0); capture.assertHasFrame(OpCode.TEXT,1); capture.assertHasFrame(OpCode.CLOSE,1); capture.assertHasFrame(OpCode.PONG,1); @@ -158,7 +159,7 @@ public class ParserTest byte mini[]; for (int i = 0; i < len; i++) { - DataFrame frame = null; + DataFrame frame; if (continuation) { frame = new ContinuationFrame(); @@ -180,12 +181,10 @@ public class ParserTest send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); ByteBuffer completeBuf = UnitGenerator.generate(send); - UnitParser parser = new UnitParser(); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); parser.parse(completeBuf); - capture.assertErrorCount(0); capture.assertHasFrame(OpCode.TEXT,textCount); capture.assertHasFrame(OpCode.CONTINUATION,continuationCount); capture.assertHasFrame(OpCode.CLOSE,1); @@ -199,9 +198,9 @@ public class ParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); + parser.parse(buf); capture.assertNoErrors(); @@ -227,9 +226,8 @@ public class ParserTest // Parse, in 4096 sized windows WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); while (networkBytes.remaining() > 0) { diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/PingPayloadParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/PingPayloadParserTest.java index 73123555781..23105ccf2a6 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/PingPayloadParserTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/PingPayloadParserTest.java @@ -43,9 +43,8 @@ public class PingPayloadParserTest BufferUtil.flipToFlush(buf,0); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); parser.parse(buf); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java index 969b56251be..c7ffdb28168 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java @@ -40,9 +40,8 @@ public class RFC6455ExamplesParserTest public void testFragmentedUnmaskedTextMessage() { WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); ByteBuffer buf = ByteBuffer.allocate(16); BufferUtil.clearToFill(buf); @@ -88,9 +87,8 @@ public class RFC6455ExamplesParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); parser.parse(buf); capture.assertNoErrors(); @@ -112,9 +110,8 @@ public class RFC6455ExamplesParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); parser.parse(buf); capture.assertNoErrors(); @@ -143,9 +140,8 @@ public class RFC6455ExamplesParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); parser.parse(buf); capture.assertNoErrors(); @@ -182,9 +178,8 @@ public class RFC6455ExamplesParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); parser.parse(buf); capture.assertNoErrors(); @@ -213,9 +208,8 @@ public class RFC6455ExamplesParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); parser.parse(buf); capture.assertNoErrors(); @@ -237,9 +231,8 @@ public class RFC6455ExamplesParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + UnitParser parser = new UnitParser(policy,capture); parser.parse(buf); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/TextPayloadParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/TextPayloadParserTest.java index 19c7982626a..9bc0061614e 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/TextPayloadParserTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/TextPayloadParserTest.java @@ -35,10 +35,15 @@ import org.eclipse.jetty.websocket.common.test.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.test.UnitParser; import org.eclipse.jetty.websocket.common.util.MaskedByteBuffer; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class TextPayloadParserTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Test public void testFrameTooLargeDueToPolicy() throws Exception { @@ -59,13 +64,13 @@ public class TextPayloadParserTest MaskedByteBuffer.putMask(buf); MaskedByteBuffer.putPayload(buf,utf); buf.flip(); - - UnitParser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); - parser.parseQuietly(buf); + UnitParser parser = new UnitParser(policy,capture); + + expectedException.expect(MessageTooLargeException.class); + parser.parse(buf); - capture.assertHasErrors(MessageTooLargeException.class,1); capture.assertHasNoFrames(); MessageTooLargeException err = (MessageTooLargeException)capture.getErrors().poll(); @@ -75,7 +80,7 @@ public class TextPayloadParserTest @Test public void testLongMaskedText() throws Exception { - StringBuffer sb = new StringBuffer(); ; + StringBuilder sb = new StringBuilder(); for (int i = 0; i < 3500; i++) { sb.append("Hell\uFF4f Big W\uFF4Frld "); @@ -97,12 +102,10 @@ public class TextPayloadParserTest WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); policy.setMaxTextMessageSize(100000); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(buf); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); WebSocketFrame txt = capture.getFrames().poll(); Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); @@ -111,7 +114,7 @@ public class TextPayloadParserTest @Test public void testMediumMaskedText() throws Exception { - StringBuffer sb = new StringBuffer(); ; + StringBuilder sb = new StringBuilder(); for (int i = 0; i < 14; i++) { sb.append("Hell\uFF4f Medium W\uFF4Frld "); @@ -132,12 +135,10 @@ public class TextPayloadParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(buf); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); WebSocketFrame txt = capture.getFrames().poll(); Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); @@ -169,12 +170,10 @@ public class TextPayloadParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(buf); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); capture.assertHasFrame(OpCode.CONTINUATION,1); WebSocketFrame txt = capture.getFrames().poll(); @@ -197,12 +196,10 @@ public class TextPayloadParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(buf); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); WebSocketFrame txt = capture.getFrames().poll(); Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); @@ -223,12 +220,10 @@ public class TextPayloadParserTest buf.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(buf); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.TEXT,1); WebSocketFrame txt = capture.getFrames().poll(); Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java index 2e4d6f091ff..925dcb27500 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java @@ -304,10 +304,9 @@ public class TestABCase1_1 } expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -338,10 +337,9 @@ public class TestABCase1_1 } expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -372,10 +370,9 @@ public class TestABCase1_1 } expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -406,10 +403,9 @@ public class TestABCase1_1 } expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -443,9 +439,8 @@ public class TestABCase1_1 expected.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); policy.setMaxTextMessageSize(length); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -480,9 +475,8 @@ public class TestABCase1_1 WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); policy.setMaxTextMessageSize(length); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -503,10 +497,9 @@ public class TestABCase1_1 { (byte)0x81, (byte)0x00 }); expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java index ba883673525..47e331478d7 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java @@ -323,10 +323,9 @@ public class TestABCase1_2 } expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -357,10 +356,9 @@ public class TestABCase1_2 } expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -391,10 +389,9 @@ public class TestABCase1_2 } expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -425,10 +422,9 @@ public class TestABCase1_2 } expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -461,9 +457,8 @@ public class TestABCase1_2 expected.flip(); WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); policy.setMaxBinaryMessageSize(length); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -498,9 +493,8 @@ public class TestABCase1_2 WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); policy.setMaxBinaryMessageSize(length); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); @@ -521,10 +515,9 @@ public class TestABCase1_2 { (byte)0x82, (byte)0x00 }); expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); capture.assertNoErrors(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java index df12cd6388d..f0b749f31c9 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java @@ -39,11 +39,16 @@ import org.eclipse.jetty.websocket.common.test.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.test.UnitGenerator; import org.eclipse.jetty.websocket.common.test.UnitParser; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class TestABCase2 { - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); @Test public void testGenerate125OctetPingCase2_4() @@ -184,13 +189,11 @@ public class TestABCase2 expected.put(bytes); expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.PING,1); Frame pActual = capture.getFrames().poll(); @@ -214,13 +217,11 @@ public class TestABCase2 expected.put(bytes); expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.PING,1); Frame pActual = capture.getFrames().poll(); @@ -237,13 +238,11 @@ public class TestABCase2 { (byte)0x89, (byte)0x00 }); expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.PING,1); Frame pActual = capture.getFrames().poll(); @@ -268,13 +267,11 @@ public class TestABCase2 expected.put(messageBytes); expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.PING,1); Frame pActual = capture.getFrames().poll(); @@ -311,13 +308,12 @@ public class TestABCase2 expected.put(bytes); expected.flip(); - - UnitParser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); - parser.parseQuietly(expected); + UnitParser parser = new UnitParser(policy,capture); - Assert.assertEquals("error should be returned for too large of ping payload",1,capture.getErrorCount(ProtocolException.class)); + expectedException.expect(ProtocolException.class); + parser.parse(expected); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java index fe7b4ae5eef..96a400c84b8 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java @@ -18,21 +18,25 @@ package org.eclipse.jetty.websocket.common.ab; +import static org.hamcrest.CoreMatchers.containsString; + import java.nio.ByteBuffer; -import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.test.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.test.UnitParser; -import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class TestABCase4 { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + private WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); @Test @@ -43,28 +47,13 @@ public class TestABCase4 expected.put(new byte[] { (byte)0x8b, 0x00 }); expected.flip(); - + IncomingFramesCapture capture = new IncomingFramesCapture(); - - try (StacklessLogging logging = new StacklessLogging(Parser.class)) - { - Parser parser = new UnitParser(policy); - parser.setIncomingFramesHandler(capture); - try - { - parser.parse(expected); - } - catch (ProtocolException ignore) - { - // ignore - } - } - - Assert.assertEquals("error on undefined opcode",1,capture.getErrorCount(WebSocketException.class)); - - Throwable known = capture.getErrors().poll(); - - Assert.assertTrue("undefined option should be in message",known.getMessage().contains("Unknown opcode: 11")); + Parser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(containsString("Unknown opcode: 11")); + parser.parse(expected); } @Test @@ -77,26 +66,11 @@ public class TestABCase4 expected.flip(); IncomingFramesCapture capture = new IncomingFramesCapture(); - - try (StacklessLogging logging = new StacklessLogging(Parser.class)) - { - Parser parser = new UnitParser(policy); - parser.setIncomingFramesHandler(capture); - try - { - parser.parse(expected); - } - catch (ProtocolException ignore) - { - // ignore - } - } - - Assert.assertEquals("error on undefined opcode",1,capture.getErrorCount(WebSocketException.class)); - - Throwable known = capture.getErrors().poll(); - - Assert.assertTrue("undefined option should be in message",known.getMessage().contains("Unknown opcode: 12")); + Parser parser = new UnitParser(policy, capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(containsString("Unknown opcode: 12")); + parser.parse(expected); } @Test @@ -107,28 +81,13 @@ public class TestABCase4 expected.put(new byte[] { (byte)0x83, 0x00 }); expected.flip(); - + IncomingFramesCapture capture = new IncomingFramesCapture(); - - try (StacklessLogging logging = new StacklessLogging(Parser.class)) - { - Parser parser = new UnitParser(policy); - parser.setIncomingFramesHandler(capture); - try - { - parser.parse(expected); - } - catch (ProtocolException ignore) - { - // ignore - } - } - - Assert.assertEquals("error on undefined opcode",1,capture.getErrorCount(WebSocketException.class)); - - Throwable known = capture.getErrors().poll(); - - Assert.assertTrue("undefined option should be in message",known.getMessage().contains("Unknown opcode: 3")); + Parser parser = new UnitParser(policy, capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(containsString("Unknown opcode: 3")); + parser.parse(expected); } @Test @@ -141,25 +100,10 @@ public class TestABCase4 expected.flip(); IncomingFramesCapture capture = new IncomingFramesCapture(); - - try (StacklessLogging logging = new StacklessLogging(Parser.class)) - { - Parser parser = new UnitParser(policy); - parser.setIncomingFramesHandler(capture); - try - { - parser.parse(expected); - } - catch (ProtocolException ignore) - { - // ignore - } - } - - Assert.assertEquals("error on undefined opcode",1,capture.getErrorCount(WebSocketException.class)); - - Throwable known = capture.getErrors().poll(); - - Assert.assertTrue("undefined option should be in message",known.getMessage().contains("Unknown opcode: 4")); + Parser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(containsString("Unknown opcode: 4")); + parser.parse(expected); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java index 7c523f8bcce..f0ab84a0471 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java @@ -18,7 +18,6 @@ package org.eclipse.jetty.websocket.common.ab; -import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import java.nio.ByteBuffer; @@ -39,12 +38,18 @@ import org.eclipse.jetty.websocket.common.test.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.test.UnitGenerator; import org.eclipse.jetty.websocket.common.test.UnitParser; import org.eclipse.jetty.websocket.common.util.Hex; +import org.hamcrest.CoreMatchers; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class TestABCase7_3 { - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); @Test public void testCase7_3_1GenerateEmptyClose() @@ -73,20 +78,16 @@ public class TestABCase7_3 expected.flip(); - Parser parser = new UnitParser(policy); IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.CLOSE,1); Frame pActual = capture.getFrames().poll(); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0)); - } - @Test(expected = ProtocolException.class) public void testCase7_3_2Generate1BytePayloadClose() { @@ -100,17 +101,13 @@ public class TestABCase7_3 public void testCase7_3_2Parse1BytePayloadClose() { ByteBuffer expected = Hex.asByteBuffer("880100"); - - UnitParser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); - parser.parseQuietly(expected); - - Assert.assertEquals("error on invalid close payload",1,capture.getErrorCount(ProtocolException.class)); - - ProtocolException known = (ProtocolException)capture.getErrors().poll(); - - Assert.assertThat("Payload.message",known.getMessage(),containsString("Invalid close frame payload length")); + UnitParser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(CoreMatchers.containsString("Invalid close frame payload length")); + parser.parse(expected); } @Test @@ -139,21 +136,17 @@ public class TestABCase7_3 { (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 }); expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.CLOSE,1); Frame pActual = capture.getFrames().poll(); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(2)); - } - @Test public void testCase7_3_4GenerateCloseWithStatusReason() { @@ -196,18 +189,15 @@ public class TestABCase7_3 expected.putShort((short)1000); expected.put(messageBytes); expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.CLOSE,1); Frame pActual = capture.getFrames().poll(); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(messageBytes.length + 2)); - } @@ -265,18 +255,15 @@ public class TestABCase7_3 expected.put(messageBytes); expected.flip(); - - Parser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); + Parser parser = new UnitParser(policy,capture); parser.parse(expected); - capture.assertNoErrors(); capture.assertHasFrame(OpCode.CLOSE,1); Frame pActual = capture.getFrames().poll(); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(125)); - } @Test(expected = ProtocolException.class) @@ -334,16 +321,12 @@ public class TestABCase7_3 expected.put(messageBytes); // reason expected.flip(); - - UnitParser parser = new UnitParser(policy); + IncomingFramesCapture capture = new IncomingFramesCapture(); - parser.setIncomingFramesHandler(capture); - parser.parseQuietly(expected); - - Assert.assertEquals("error on invalid close payload",1,capture.getErrorCount(ProtocolException.class)); - - ProtocolException known = (ProtocolException)capture.getErrors().poll(); - - Assert.assertThat("Payload.message",known.getMessage(),containsString("Invalid control frame payload length")); + UnitParser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(CoreMatchers.containsString("Invalid control frame payload length")); + parser.parse(expected); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/DummyIncomingFrames.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/DummyIncomingFrames.java index 1389cbbb13e..d1d4590bce7 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/DummyIncomingFrames.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/DummyIncomingFrames.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.common.extensions; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; @@ -43,7 +44,7 @@ public class DummyIncomingFrames implements IncomingFrames } @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { LOG.debug("incomingFrame({})",frame); } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/DummyOutgoingFrames.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/DummyOutgoingFrames.java index 62ff746b2c8..571ec8ac0ae 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/DummyOutgoingFrames.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/DummyOutgoingFrames.java @@ -21,7 +21,7 @@ package org.eclipse.jetty.websocket.common.extensions; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.junit.rules.TestName; @@ -45,12 +45,12 @@ public class DummyOutgoingFrames implements OutgoingFrames } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { LOG.debug("outgoingFrame({},{})",frame,callback); if (callback != null) { - callback.writeSuccess(); + callback.succeed(); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/ExtensionTool.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/ExtensionTool.java index c09dcaba615..854debf6f53 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/ExtensionTool.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/ExtensionTool.java @@ -31,6 +31,7 @@ import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.FrameCallbackAdapter; import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; @@ -57,8 +58,9 @@ public class ExtensionTool this.extConfig = ExtensionConfig.parse(parameterizedExtension); Class extClass = factory.getExtension(extConfig.getName()); Assert.assertThat("extClass", extClass, notNullValue()); - - this.parser = new UnitParser(policy); + + this.capture = new IncomingFramesCapture(); + this.parser = new UnitParser(policy,frame -> ext.incomingFrame(frame, new FrameCallbackAdapter())); } public String getRequestedExtParams() @@ -68,15 +70,12 @@ public class ExtensionTool public void assertNegotiated(String expectedNegotiation) { - this.ext = (Extension)factory.newInstance(extConfig); - - this.capture = new IncomingFramesCapture(); + this.ext = factory.newInstance(extConfig); this.ext.setNextIncomingFrames(capture); this.parser.configureFromExtensions(Collections.singletonList(ext)); - this.parser.setIncomingFramesHandler(ext); } - + public void parseIncomingHex(String... rawhex) { int parts = rawhex.length; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/FragmentExtensionTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/FragmentExtensionTest.java index 7e3898b7895..85dc98efc45 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/FragmentExtensionTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/FragmentExtensionTest.java @@ -32,6 +32,7 @@ import org.eclipse.jetty.websocket.api.BatchMode; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.FrameCallbackAdapter; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.extensions.fragment.FragmentExtension; @@ -77,7 +78,7 @@ public class FragmentExtensionTest for (String q : quote) { Frame frame = new TextFrame().setPayload(q); - ext.incomingFrame(frame); + ext.incomingFrame(frame, new FrameCallbackAdapter()); } int len = quote.size(); @@ -121,7 +122,7 @@ public class FragmentExtensionTest String payload = "Are you there?"; Frame ping = new PingFrame().setPayload(payload); - ext.incomingFrame(ping); + ext.incomingFrame(ping, new FrameCallbackAdapter()); capture.assertFrameCount(1); capture.assertHasFrame(OpCode.PING, 1); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/IdentityExtensionTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/IdentityExtensionTest.java index fe685ce0d9e..649d79c10b0 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/IdentityExtensionTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/IdentityExtensionTest.java @@ -28,6 +28,7 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.api.BatchMode; import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.FrameCallbackAdapter; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.extensions.identity.IdentityExtension; @@ -52,7 +53,7 @@ public class IdentityExtensionTest ext.setNextIncomingFrames(capture); Frame frame = new TextFrame().setPayload("hello"); - ext.incomingFrame(frame); + ext.incomingFrame(frame, new FrameCallbackAdapter()); capture.assertFrameCount(1); capture.assertHasFrame(OpCode.TEXT, 1); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/CapturedHexPayloads.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/CapturedHexPayloads.java index a90afab0298..8381c5e04a6 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/CapturedHexPayloads.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/CapturedHexPayloads.java @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.util.Hex; @@ -32,13 +32,13 @@ public class CapturedHexPayloads implements OutgoingFrames private List captured = new ArrayList<>(); @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { String hexPayload = Hex.asHex(frame.getPayload()); captured.add(hexPayload); if (callback != null) { - callback.writeSuccess(); + callback.succeed(); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/DeflateFrameExtensionTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/DeflateFrameExtensionTest.java index e930452d2d4..ac2c9a59764 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/DeflateFrameExtensionTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/DeflateFrameExtensionTest.java @@ -39,12 +39,13 @@ import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; +import org.eclipse.jetty.websocket.common.FrameCallbackAdapter; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.Parser; @@ -86,10 +87,8 @@ public class DeflateFrameExtensionTest extends AbstractExtensionTest // Wire up stack ext.setNextIncomingFrames(capture); - Parser parser = new UnitParser(policy); + Parser parser = new UnitParser(policy, frame -> ext.incomingFrame(frame, new FrameCallbackAdapter())); parser.configureFromExtensions(Collections.singletonList(ext)); - parser.setIncomingFramesHandler(ext); - parser.parse(ByteBuffer.wrap(raw)); int len = expectedTextDatas.length; @@ -410,11 +409,11 @@ public class DeflateFrameExtensionTest extends AbstractExtensionTest clientExtension.setNextOutgoingFrames(new OutgoingFrames() { @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { LOG.debug("outgoingFrame({})", frame); - serverExtension.incomingFrame(frame); - callback.writeSuccess(); + serverExtension.incomingFrame(frame, callback); + callback.succeed(); } }); @@ -422,7 +421,7 @@ public class DeflateFrameExtensionTest extends AbstractExtensionTest serverExtension.setNextIncomingFrames(new IncomingFrames() { @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { LOG.debug("incomingFrame({})", frame); try diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtensionTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtensionTest.java index 3486a4b9998..14c49cde585 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtensionTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtensionTest.java @@ -33,6 +33,7 @@ import org.eclipse.jetty.websocket.api.BatchMode; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.FrameCallbackAdapter; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.extensions.AbstractExtensionTest; @@ -245,7 +246,7 @@ public class PerMessageDeflateExtensionTest extends AbstractExtensionTest String payload = "Are you there?"; Frame ping = new PingFrame().setPayload(payload); - ext.incomingFrame(ping); + ext.incomingFrame(ping, new FrameCallbackAdapter()); capture.assertFrameCount(1); capture.assertHasFrame(OpCode.PING, 1); @@ -291,7 +292,7 @@ public class PerMessageDeflateExtensionTest extends AbstractExtensionTest { TextFrame frame = new TextFrame().setPayload(q); frame.setRsv1(false); // indication to extension that frame is not compressed (ie: a normal frame) - ext.incomingFrame(frame); + ext.incomingFrame(frame, new FrameCallbackAdapter()); } int len = quote.size(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctionsTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctionsTest.java index 94573f94848..a0ba3d42407 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctionsTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctionsTest.java @@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketConnectionListener; @@ -41,6 +42,8 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.CloseInfo; +import org.eclipse.jetty.websocket.common.frames.ContinuationFrame; +import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.io.LocalWebSocketSession; import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; @@ -108,7 +111,7 @@ public class CommonEndpointFunctionsTest { // Trigger Events endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hello?", UTF8), true); + endpointFunctions.onText(new TextFrame().setPayload("Hello?").setFin(true), new FrameCallback.Adapter()); endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); } @@ -143,7 +146,7 @@ public class CommonEndpointFunctionsTest { // Trigger Events endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hello Text", UTF8), true); + endpointFunctions.onText(new TextFrame().setPayload("Hello Text").setFin(true), new FrameCallback.Adapter()); endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); } @@ -188,7 +191,7 @@ public class CommonEndpointFunctionsTest { // Trigger Events endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hello Text Stream", UTF8), true); + endpointFunctions.onText(new TextFrame().setPayload("Hello Text Stream").setFin(true), new FrameCallback.Adapter()); endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); } @@ -209,10 +212,10 @@ public class CommonEndpointFunctionsTest { // Trigger Events endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hel"), false); - endpointFunctions.onText(BufferUtil.toBuffer("lo "), false); - endpointFunctions.onText(BufferUtil.toBuffer("Wor"), false); - endpointFunctions.onText(BufferUtil.toBuffer("ld"), true); + endpointFunctions.onText(new TextFrame().setPayload("Hel").setFin(false), new FrameCallback.Adapter()); + endpointFunctions.onText(new ContinuationFrame().setPayload("lo ").setFin(false), new FrameCallback.Adapter()); + endpointFunctions.onText(new ContinuationFrame().setPayload("Wor").setFin(false), new FrameCallback.Adapter()); + endpointFunctions.onText(new ContinuationFrame().setPayload("ld").setFin(true), new FrameCallback.Adapter()); endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); } @@ -248,9 +251,9 @@ public class CommonEndpointFunctionsTest { // Trigger Events endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hello"), false); - endpointFunctions.onText(BufferUtil.toBuffer(" "), false); - endpointFunctions.onText(BufferUtil.toBuffer("World"), true); + endpointFunctions.onText(new TextFrame().setPayload("Hello").setFin(false), new FrameCallback.Adapter()); + endpointFunctions.onText(new ContinuationFrame().setPayload(" ").setFin(false), new FrameCallback.Adapter()); + endpointFunctions.onText(new ContinuationFrame().setPayload("World").setFin(true), new FrameCallback.Adapter()); endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java index d60b10391c2..00130d3b18d 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java @@ -26,12 +26,11 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.ExecutorThreadPool; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.SuspendToken; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.ConnectionState; import org.eclipse.jetty.websocket.common.LogicalConnection; @@ -39,14 +38,13 @@ import org.eclipse.jetty.websocket.common.io.IOState.ConnectionStateListener; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; import org.junit.rules.TestName; -public class LocalWebSocketConnection implements LogicalConnection, IncomingFrames, ConnectionStateListener +public class LocalWebSocketConnection implements LogicalConnection, ConnectionStateListener { private static final Logger LOG = Log.getLogger(LocalWebSocketConnection.class); private final String id; private final ByteBufferPool bufferPool; private final Executor executor; private WebSocketPolicy policy; - private IncomingFrames incoming; private IOState ioState = new IOState(); public LocalWebSocketConnection(ByteBufferPool bufferPool) @@ -127,11 +125,6 @@ public class LocalWebSocketConnection implements LogicalConnection, IncomingFram return 0; } - public IncomingFrames getIncoming() - { - return incoming; - } - @Override public IOState getIOState() { @@ -162,18 +155,6 @@ public class LocalWebSocketConnection implements LogicalConnection, IncomingFram return null; } - @Override - public void incomingError(Throwable e) - { - incoming.incomingError(e); - } - - @Override - public void incomingFrame(Frame frame) - { - incoming.incomingFrame(frame); - } - @Override public boolean isOpen() { @@ -217,7 +198,7 @@ public class LocalWebSocketConnection implements LogicalConnection, IncomingFram } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { } @@ -231,12 +212,6 @@ public class LocalWebSocketConnection implements LogicalConnection, IncomingFram { } - @Override - public void setNextIncomingFrames(IncomingFrames incoming) - { - this.incoming = incoming; - } - public void setPolicy(WebSocketPolicy policy) { this.policy = policy; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageInputStreamTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageInputStreamTest.java index ab56a32597b..dd3871c636f 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageInputStreamTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageInputStreamTest.java @@ -27,7 +27,11 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.websocket.api.FrameCallback; +import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.common.frames.BinaryFrame; +import org.eclipse.jetty.websocket.common.frames.ContinuationFrame; +import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule; import org.junit.Assert; import org.junit.Rule; @@ -48,9 +52,10 @@ public class MessageInputStreamTest try (MessageInputStream stream = new MessageInputStream()) { // Append a single message (simple, short) - ByteBuffer payload = BufferUtil.toBuffer("Hello World",StandardCharsets.UTF_8); - boolean fin = true; - stream.accept(payload,fin); + TextFrame frame = new TextFrame(); + frame.setPayload("Hello World"); + frame.setFin(true); + stream.accept(frame, new FrameCallback.Adapter()); // Read entire message it from the stream. byte buf[] = new byte[32]; @@ -80,14 +85,12 @@ public class MessageInputStreamTest try { startLatch.countDown(); - boolean fin = false; TimeUnit.MILLISECONDS.sleep(200); - stream.accept(BufferUtil.toBuffer("Saved",StandardCharsets.UTF_8),fin); + stream.accept(new BinaryFrame().setPayload("Saved").setFin(false), new FrameCallback.Adapter()); TimeUnit.MILLISECONDS.sleep(200); - stream.accept(BufferUtil.toBuffer(" by ",StandardCharsets.UTF_8),fin); - fin = true; + stream.accept(new ContinuationFrame().setPayload(" by ").setFin(false), new FrameCallback.Adapter()); TimeUnit.MILLISECONDS.sleep(200); - stream.accept(BufferUtil.toBuffer("Zero",StandardCharsets.UTF_8),fin); + stream.accept(new ContinuationFrame().setPayload("Zero").setFin(true), new FrameCallback.Adapter()); } catch (InterruptedException e) { @@ -125,10 +128,9 @@ public class MessageInputStreamTest { try { - boolean fin = true; // wait for a little bit before populating buffers TimeUnit.MILLISECONDS.sleep(400); - stream.accept(BufferUtil.toBuffer("I will conquer",StandardCharsets.UTF_8),fin); + stream.accept(new BinaryFrame().setPayload("I will conquer").setFin(true), new FrameCallback.Adapter()); } catch (InterruptedException e) { @@ -189,13 +191,14 @@ public class MessageInputStreamTest try (MessageInputStream stream = new MessageInputStream()) { // Append parts of message - ByteBuffer msg1 = BufferUtil.toBuffer("Hello ",StandardCharsets.UTF_8); - ByteBuffer msg2 = ByteBuffer.allocate(0); // what is being tested - ByteBuffer msg3 = BufferUtil.toBuffer("World",StandardCharsets.UTF_8); + WebSocketFrame msg1 = new BinaryFrame().setPayload("Hello ").setFin(false); + // what is being tested (an empty payload) + WebSocketFrame msg2 = new ContinuationFrame().setPayload(new byte[0]).setFin(false); + WebSocketFrame msg3 = new ContinuationFrame().setPayload("World").setFin(true); - stream.accept(msg1,false); - stream.accept(msg2,false); - stream.accept(msg3,true); + stream.accept(msg1, new FrameCallback.Adapter()); + stream.accept(msg2, new FrameCallback.Adapter()); + stream.accept(msg3, new FrameCallback.Adapter()); // Read entire message it from the stream. byte buf[] = new byte[32]; @@ -213,13 +216,15 @@ public class MessageInputStreamTest try (MessageInputStream stream = new MessageInputStream()) { // Append parts of message - ByteBuffer msg1 = BufferUtil.toBuffer("Hello ",StandardCharsets.UTF_8); - ByteBuffer msg2 = null; // what is being tested - ByteBuffer msg3 = BufferUtil.toBuffer("World",StandardCharsets.UTF_8); + WebSocketFrame msg1 = new BinaryFrame().setPayload("Hello ").setFin(false); + // what is being tested (a null payload) + ByteBuffer nilPayload = null; + WebSocketFrame msg2 = new ContinuationFrame().setPayload(nilPayload).setFin(false); + WebSocketFrame msg3 = new ContinuationFrame().setPayload("World").setFin(true); - stream.accept(msg1,false); - stream.accept(msg2,false); - stream.accept(msg3,true); + stream.accept(msg1, new FrameCallback.Adapter()); + stream.accept(msg2, new FrameCallback.Adapter()); + stream.accept(msg3, new FrameCallback.Adapter()); // Read entire message it from the stream. byte buf[] = new byte[32]; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java index 84188cb886e..e8d75253d18 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java @@ -22,6 +22,7 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import java.net.URI; import java.util.Arrays; import org.eclipse.jetty.toolchain.test.TestTracker; @@ -31,7 +32,7 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.io.FramePipes; -import org.eclipse.jetty.websocket.common.io.LocalWebSocketSession; +import org.eclipse.jetty.websocket.common.io.LocalWebSocketConnection; import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule; @@ -57,7 +58,7 @@ public class MessageOutputStreamTest private WebSocketPolicy policy; private TrackingSocket remoteSocket; - private LocalWebSocketSession session; + private WebSocketSession session; private WebSocketSession remoteSession; @After @@ -81,14 +82,18 @@ public class MessageOutputStreamTest // remote socket remoteSocket = new TrackingSocket("remote"); - remoteSession = new LocalWebSocketSession(containerScope,testname,remoteSocket); + URI remoteURI = new URI("ws://localhost/remote"); + LocalWebSocketConnection remoteConnection = new LocalWebSocketConnection(bufferPool); + remoteSession = new WebSocketSession(containerScope,remoteURI,remoteSocket,remoteConnection); OutgoingFrames socketPipe = FramePipes.to(remoteSession); remoteSession.start(); remoteSession.open(); // Local Session TrackingSocket localSocket = new TrackingSocket("local"); - session = new LocalWebSocketSession(containerScope,testname,localSocket); + URI localURI = new URI("ws://localhost/local"); + LocalWebSocketConnection localConnection = new LocalWebSocketConnection(bufferPool); + session = new WebSocketSession(containerScope,localURI,localSocket,localConnection); // talk to our remote socket session.setOutgoingHandler(socketPipe); @@ -98,7 +103,7 @@ public class MessageOutputStreamTest session.open(); } - @Test + @Test(timeout = 2000) public void testMultipleWrites() throws Exception { try (MessageOutputStream stream = new MessageOutputStream(session)) @@ -112,8 +117,8 @@ public class MessageOutputStreamTest String msg = remoteSocket.messageQueue.poll(); Assert.assertThat("Message",msg,allOf(containsString("byte[11]"),containsString("Hello World"))); } - - @Test + + @Test(timeout = 2000) public void testSingleWrite() throws Exception { try (MessageOutputStream stream = new MessageOutputStream(session)) @@ -125,8 +130,8 @@ public class MessageOutputStreamTest String msg = remoteSocket.messageQueue.poll(); Assert.assertThat("Message",msg,allOf(containsString("byte[11]"),containsString("Hello World"))); } - - @Test + + @Test(timeout = 2000) public void testWriteMultipleBuffers() throws Exception { int bufsize = (int)(policy.getMaxBinaryMessageBufferSize() * 2.5); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java index e8ba0086b69..937e8bff3fc 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java @@ -100,8 +100,8 @@ public class MessageWriterTest // open connection session.open(); } - - @Test + + @Test(timeout = 2000) public void testMultipleWrites() throws Exception { try (MessageWriter stream = new MessageWriter(session)) @@ -115,8 +115,8 @@ public class MessageWriterTest String msg = remoteSocket.messageQueue.poll(); Assert.assertThat("Message",msg,is("Hello World")); } - - @Test + + @Test(timeout = 20000) public void testSingleWrite() throws Exception { try (MessageWriter stream = new MessageWriter(session)) @@ -128,8 +128,8 @@ public class MessageWriterTest String msg = remoteSocket.messageQueue.poll(); Assert.assertThat("Message",msg,is("Hello World")); } - - @Test + + @Test(timeout = 2000) public void testWriteMultipleBuffers() throws Exception { int bufsize = (int)(policy.getMaxTextMessageBufferSize() * 2.5); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java index 294994bc922..ec2bb8e6234 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java @@ -54,8 +54,8 @@ import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; @@ -88,7 +88,7 @@ import org.junit.Assert; * with regards to basic IO behavior, a write should work as expected, a read should work as expected, but what byte it sends or reads is not within its * scope. */ -public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, AutoCloseable, IBlockheadClient +public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, AutoCloseable, IBlockheadClient, Parser.Handler { private class FrameReadingThread extends Thread implements Runnable, IncomingFrames { @@ -167,7 +167,7 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, } @Override - public synchronized void incomingFrame(Frame frame) + public synchronized void incomingFrame(Frame frame, FrameCallback callback) { this.frames.add(WebSocketFrame.copy(frame)); } @@ -231,7 +231,7 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, // This is a blockhead client, no point tracking leaks on this object. this.bufferPool = new MappedByteBufferPool(8192); this.generator = new Generator(policy,bufferPool); - this.parser = new Parser(policy,bufferPool); + this.parser = new Parser(policy,bufferPool,this); this.extensionFactory = new WebSocketExtensionFactory(new SimpleContainerScope(policy,bufferPool)); this.ioState = new IOState(); @@ -435,7 +435,6 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, } // configure parser - parser.setIncomingFramesHandler(extensionStack); ioState.onOpened(); LOG.debug("outgoing = {}",outgoing); @@ -591,7 +590,7 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { ByteBuffer headerBuf = generator.generateHeaderBytes(frame); if (LOG.isDebugEnabled()) @@ -605,14 +604,14 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, out.flush(); if (callback != null) { - callback.writeSuccess(); + callback.succeed(); } } catch (IOException e) { if (callback != null) { - callback.writeFailed(e); + callback.fail(e); } } finally @@ -625,7 +624,13 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, disconnect(); } } - + + @Override + public void onFrame(Frame frame) + { + // TODO + } + public EventQueue readFrames(int expectedFrameCount, int timeoutDuration, TimeUnit timeoutUnit) throws Exception { frameReader.frames.awaitEventCount(expectedFrameCount,timeoutDuration,timeoutUnit); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java index 2522e4f2302..0ea22a2aee4 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java @@ -18,7 +18,8 @@ package org.eclipse.jetty.websocket.common.test; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import java.io.BufferedReader; import java.io.IOException; @@ -46,15 +47,16 @@ import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.Frame.Type; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; -import org.eclipse.jetty.websocket.api.extensions.Frame.Type; import org.eclipse.jetty.websocket.common.AcceptHash; import org.eclipse.jetty.websocket.common.CloseInfo; +import org.eclipse.jetty.websocket.common.FrameCallbackAdapter; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.Parser; @@ -88,7 +90,8 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames private Map extraResponseHeaders = new HashMap<>(); private OutgoingFrames outgoing = this; - + private ExtensionStack extensionStack; + public BlockheadServerConnection(Socket socket) { this.socket = socket; @@ -98,7 +101,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames this.policy.setMaxTextMessageSize(100000); // This is a blockhead server connection, no point tracking leaks on this object. this.bufferPool = new MappedByteBufferPool(BUFFER_SIZE); - this.parser = new Parser(policy,bufferPool); + this.parser = new Parser(policy,bufferPool,frame -> extensionStack.incomingFrame(frame, new FrameCallbackAdapter())); this.parseCount = new AtomicInteger(0); this.generator = new Generator(policy,bufferPool,false); this.extensionRegistry = new WebSocketExtensionFactory(new SimpleContainerScope(policy,bufferPool)); @@ -214,7 +217,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames } @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) { LOG.debug("incoming({})",frame); int count = parseCount.incrementAndGet(); @@ -222,7 +225,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames { LOG.info("Server parsed {} frames",count); } - incomingFrames.incomingFrame(WebSocketFrame.copy(frame)); + incomingFrames.incomingFrame(WebSocketFrame.copy(frame), callback); if (frame.getOpCode() == OpCode.CLOSE) { @@ -245,7 +248,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { ByteBuffer headerBuf = generator.generateHeaderBytes(frame); if (LOG.isDebugEnabled()) @@ -261,7 +264,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames out.flush(); if (callback != null) { - callback.writeSuccess(); + callback.succeed(); } if (frame.getOpCode() == OpCode.CLOSE) @@ -273,7 +276,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames { if (callback != null) { - callback.writeFailed(t); + callback.fail(t); } } } @@ -514,7 +517,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames Assert.assertThat("Request: Sec-WebSocket-Key",key,notNullValue()); // collect extensions configured in response header - ExtensionStack extensionStack = new ExtensionStack(extensionRegistry); + extensionStack = new ExtensionStack(extensionRegistry); extensionStack.negotiate(extensionConfigs); // Start with default routing @@ -535,9 +538,6 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames throw new IOException("Unable to start Extension Stack"); } - // Configure Parser - parser.setIncomingFramesHandler(extensionStack); - // Setup Response StringBuilder resp = new StringBuilder(); resp.append("HTTP/1.1 101 Upgrade\r\n"); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/DummyConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/DummyConnection.java index 6a755eaff23..e8b6bb9ee1f 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/DummyConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/DummyConnection.java @@ -25,11 +25,10 @@ import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.SuspendToken; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.LogicalConnection; import org.eclipse.jetty.websocket.common.io.IOState; @@ -134,9 +133,9 @@ public class DummyConnection implements LogicalConnection } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { - callback.writeSuccess(); + callback.succeed(); } @Override @@ -149,13 +148,6 @@ public class DummyConnection implements LogicalConnection { } - @Override - public void setNextIncomingFrames(IncomingFrames incoming) - { - if (LOG.isDebugEnabled()) - LOG.debug("setNextIncomingFrames({})", incoming); - } - @Override public SuspendToken suspend() { diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IncomingFramesCapture.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IncomingFramesCapture.java index 403b9f4ff0d..de602305352 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IncomingFramesCapture.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IncomingFramesCapture.java @@ -27,19 +27,22 @@ import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.common.OpCode; +import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.junit.Assert; -public class IncomingFramesCapture implements IncomingFrames +public class IncomingFramesCapture implements Parser.Handler, IncomingFrames { private static final Logger LOG = Log.getLogger(IncomingFramesCapture.class); private EventQueue frames = new EventQueue<>(); private EventQueue errors = new EventQueue<>(); + @Deprecated public void assertErrorCount(int expectedCount) { Assert.assertThat("Captured error count",errors.size(),is(expectedCount)); @@ -63,6 +66,7 @@ public class IncomingFramesCapture implements IncomingFrames Assert.assertThat("Captured frame count",frames.size(),is(expectedCount)); } + @Deprecated public void assertHasErrors(Class errorType, int expectedCount) { Assert.assertThat(errorType.getSimpleName(),getErrorCount(errorType),is(expectedCount)); @@ -84,6 +88,7 @@ public class IncomingFramesCapture implements IncomingFrames Assert.assertThat("Frame count",frames.size(),is(0)); } + @Deprecated public void assertNoErrors() { Assert.assertThat("Error count",errors.size(),is(0)); @@ -105,6 +110,7 @@ public class IncomingFramesCapture implements IncomingFrames } } + @Deprecated public int getErrorCount(Class errorType) { int count = 0; @@ -118,6 +124,7 @@ public class IncomingFramesCapture implements IncomingFrames return count; } + @Deprecated public Queue getErrors() { return errors; @@ -140,23 +147,26 @@ public class IncomingFramesCapture implements IncomingFrames { return frames; } - + @Override - public void incomingError(Throwable e) + public void incomingError(Throwable t) { - LOG.debug(e); - errors.add(e); + errors.add(t); } - + @Override - public void incomingFrame(Frame frame) + public void incomingFrame(Frame frame, FrameCallback callback) + { + onFrame(frame); + } + + @Override + public void onFrame(Frame frame) { WebSocketFrame copy = WebSocketFrame.copy(frame); - // TODO: might need to make this optional (depending on use by client vs server tests) - // Assert.assertThat("frame.masking must be set",frame.isMasked(),is(true)); frames.add(copy); } - + public int size() { return frames.size(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/OutgoingFramesCapture.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/OutgoingFramesCapture.java index 03d14906ad3..7752b656866 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/OutgoingFramesCapture.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/OutgoingFramesCapture.java @@ -18,21 +18,21 @@ package org.eclipse.jetty.websocket.common.test; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.is; + import java.nio.ByteBuffer; import java.util.LinkedList; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.junit.Assert; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.hamcrest.Matchers.is; - public class OutgoingFramesCapture implements OutgoingFrames { private LinkedList frames = new LinkedList<>(); @@ -87,7 +87,7 @@ public class OutgoingFramesCapture implements OutgoingFrames } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { frames.add(WebSocketFrame.copy(frame)); // Consume bytes @@ -96,7 +96,7 @@ public class OutgoingFramesCapture implements OutgoingFrames // notify callback if (callback != null) { - callback.writeSuccess(); + callback.succeed(); } } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/OutgoingNetworkBytesCapture.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/OutgoingNetworkBytesCapture.java index 756d7341c4d..ed23d0efd58 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/OutgoingNetworkBytesCapture.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/OutgoingNetworkBytesCapture.java @@ -29,7 +29,7 @@ import java.util.Locale; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.FrameCallback; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; import org.eclipse.jetty.websocket.common.Generator; @@ -63,7 +63,7 @@ public class OutgoingNetworkBytesCapture implements OutgoingFrames } @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + public void outgoingFrame(Frame frame, FrameCallback callback, BatchMode batchMode) { ByteBuffer buf = ByteBuffer.allocate(Generator.MAX_HEADER_LENGTH + frame.getPayloadLength()); generator.generateWholeFrame(frame,buf); @@ -71,7 +71,7 @@ public class OutgoingNetworkBytesCapture implements OutgoingFrames captured.add(buf); if (callback != null) { - callback.writeSuccess(); + callback.succeed(); } } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/UnitParser.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/UnitParser.java index 11c7e7d0c32..018948b6dfa 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/UnitParser.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/UnitParser.java @@ -28,14 +28,9 @@ import org.eclipse.jetty.websocket.common.Parser; public class UnitParser extends Parser { - public UnitParser() + public UnitParser(WebSocketPolicy policy, Parser.Handler handler) { - this(WebSocketPolicy.newServerPolicy()); - } - - public UnitParser(WebSocketPolicy policy) - { - super(policy,new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged())); + super(policy,new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged()),handler); } private void parsePartial(ByteBuffer buf, int numBytes) @@ -52,6 +47,7 @@ public class UnitParser extends Parser * Use if you know the parse will cause an exception and just don't wnat to make the test console all noisy. * @param buf the buffer to parse */ + @Deprecated public void parseQuietly(ByteBuffer buf) { try (StacklessLogging suppress = new StacklessLogging(Parser.class)) diff --git a/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties b/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties index 95874c8167d..9b7c9fa832e 100644 --- a/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties @@ -6,4 +6,4 @@ org.eclipse.jetty.LEVEL=WARN # org.eclipse.jetty.websocket.io.payload.LEVEL=DEBUG # org.eclipse.jetty.websocket.common.extensions.LEVEL=DEBUG # org.eclipse.jetty.websocket.common.message.LEVEL=DEBUG -org.eclipse.jetty.websocket.common.function.LEVEL=DEBUG +# org.eclipse.jetty.websocket.common.function.LEVEL=DEBUG diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java index 83dff8cd411..3b2010f864a 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java @@ -26,14 +26,14 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.common.extensions.ExtensionStack; import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; public class WebSocketServerConnection extends AbstractWebSocketConnection implements Connection.UpgradeTo { - public WebSocketServerConnection(EndPoint endp, Executor executor, Scheduler scheduler, WebSocketPolicy policy, ByteBufferPool bufferPool) + public WebSocketServerConnection(EndPoint endp, Executor executor, Scheduler scheduler, WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack) { - super(endp,executor,scheduler,policy,bufferPool); + super(endp,executor,scheduler,policy,bufferPool,extensionStack); } @Override @@ -47,10 +47,4 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection imple { return getEndPoint().getRemoteAddress(); } - - @Override - public void setNextIncomingFrames(IncomingFrames incoming) - { - getParser().setIncomingFramesHandler(incoming); - } } diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java index 9ce1c4c88f8..bfe1ea4ec60 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java @@ -560,7 +560,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc ByteBufferPool bufferPool = connector.getByteBufferPool(); // Setup websocket connection - AbstractWebSocketConnection wsConnection = new WebSocketServerConnection(endp, executor, scheduler, getPolicy().clonePolicy(), bufferPool); + AbstractWebSocketConnection wsConnection = new WebSocketServerConnection(endp, executor, scheduler, getPolicy().clonePolicy(), bufferPool, extensionStack); extensionStack.setPolicy(wsConnection.getPolicy()); extensionStack.configure(wsConnection.getParser()); @@ -581,7 +581,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc wsConnection.addListener(session); // Setup Incoming Routing - wsConnection.setNextIncomingFrames(extensionStack); extensionStack.setNextIncoming(session); // Setup Outgoing Routing