message = new CompletableFuture<>();
private boolean first = true;
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/PartialStringMessageSinkTest.java b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/PartialStringMessageSinkTest.java
index 4d0985d9159..22fed88f870 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/PartialStringMessageSinkTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/PartialStringMessageSinkTest.java
@@ -51,7 +51,7 @@ public class PartialStringMessageSinkTest
@BeforeEach
public void before() throws Exception
{
- messageSink = new PartialStringMessageSink(coreSession, endpoint.getMethodHandle());
+ messageSink = new PartialStringMessageSink(coreSession, endpoint.getMethodHandle(), true);
}
@Test
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/StringMessageSinkTest.java b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/StringMessageSinkTest.java
index 3feffda0e53..a5448b74b45 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/StringMessageSinkTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/StringMessageSinkTest.java
@@ -44,7 +44,7 @@ public class StringMessageSinkTest
@Test
public void testMaxMessageSize() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle());
+ StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
ByteBuffer utf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90, (byte)0x8D, (byte)0x88});
FutureCallback callback = new FutureCallback();
@@ -60,7 +60,7 @@ public class StringMessageSinkTest
@Test
public void testValidUtf8() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle());
+ StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
ByteBuffer utf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90, (byte)0x8D, (byte)0x88});
FutureCallback callback = new FutureCallback();
@@ -73,7 +73,7 @@ public class StringMessageSinkTest
@Test
public void testUtf8Continuation() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle());
+ StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
ByteBuffer firstUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90});
ByteBuffer continuationUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0x8D, (byte)0x88});
@@ -91,7 +91,7 @@ public class StringMessageSinkTest
@Test
public void testInvalidSingleFrameUtf8() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle());
+ StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
ByteBuffer invalidUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90, (byte)0x8D});
FutureCallback callback = new FutureCallback();
@@ -106,7 +106,7 @@ public class StringMessageSinkTest
@Test
public void testInvalidMultiFrameUtf8() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle());
+ StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
ByteBuffer firstUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90});
ByteBuffer continuationUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0x8D});
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/BatchMode.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/BatchMode.java
deleted file mode 100644
index c5607e8651f..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/BatchMode.java
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-/**
- * The possible batch modes when enqueuing outgoing frames.
- */
-public enum BatchMode
-{
- /**
- * Implementers are free to decide whether to send or not frames
- * to the network layer.
- */
- AUTO,
-
- /**
- * Implementers must batch frames.
- */
- ON,
-
- /**
- * Implementers must send frames to the network layer.
- */
- OFF;
-
- public static BatchMode max(BatchMode one, BatchMode two)
- {
- // Return the BatchMode that has the higher priority, where AUTO < ON < OFF.
- return one.ordinal() < two.ordinal() ? two : one;
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Callback.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Callback.java
new file mode 100644
index 00000000000..74e90854ecf
--- /dev/null
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Callback.java
@@ -0,0 +1,105 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.api;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+
+/**
+ * Callback for Write events.
+ *
+ * NOTE: We don't expose org.eclipse.jetty.util.Callback here as that would complicate matters with the WebAppContext's classloader isolation.
+ */
+public interface Callback
+{
+ Callback NOOP = new Callback()
+ {
+ };
+
+ /**
+ * Creates a callback from the given success and failure lambdas.
+ *
+ * @param success called when the callback succeeds
+ * @param failure called when the callback fails
+ * @return a new callback
+ */
+ static Callback from(Runnable success, Consumer failure)
+ {
+ return new Callback()
+ {
+ @Override
+ public void succeed()
+ {
+ success.run();
+ }
+
+ @Override
+ public void fail(Throwable x)
+ {
+ failure.accept(x);
+ }
+ };
+ }
+
+ /**
+ *
+ * Callback invoked when the write succeeds.
+ *
+ *
+ * @see #fail(Throwable)
+ */
+ default void succeed()
+ {
+ }
+
+ /**
+ *
+ * Callback invoked when the write fails.
+ *
+ *
+ * @param x the reason for the write failure
+ */
+ default void fail(Throwable x)
+ {
+ }
+
+ class Completable extends CompletableFuture implements Callback
+ {
+ public static Completable with(Consumer consumer)
+ {
+ Completable completable = new Completable();
+ consumer.accept(completable);
+ return completable;
+ }
+
+ @Override
+ public void succeed()
+ {
+ complete(null);
+ }
+
+ @Override
+ public void fail(Throwable x)
+ {
+ completeExceptionally(x);
+ }
+
+ public Completable compose(Consumer consumer)
+ {
+ Completable completable = new Completable();
+ thenAccept(ignored -> consumer.accept(completable));
+ return completable;
+ }
+ }
+}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/CloseStatus.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/CloseStatus.java
deleted file mode 100644
index 4027e2751ce..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/CloseStatus.java
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-public class CloseStatus
-{
- private static final int MAX_CONTROL_PAYLOAD = 125;
- public static final int MAX_REASON_PHRASE = MAX_CONTROL_PAYLOAD - 2;
-
- private final int code;
- private final String phrase;
-
- /**
- * Creates a reason for closing a web socket connection with the given code and reason phrase.
- *
- * @param closeCode the close code
- * @param reasonPhrase the reason phrase
- * @see StatusCode
- */
- public CloseStatus(int closeCode, String reasonPhrase)
- {
- this.code = closeCode;
- this.phrase = reasonPhrase;
- if (reasonPhrase.length() > MAX_REASON_PHRASE)
- {
- throw new IllegalArgumentException("Phrase exceeds maximum length of " + MAX_REASON_PHRASE);
- }
- }
-
- public int getCode()
- {
- return code;
- }
-
- public String getPhrase()
- {
- return phrase;
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Configurable.java
similarity index 80%
rename from jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java
rename to jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Configurable.java
index ec343d76f02..acaf306ea50 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPolicy.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Configurable.java
@@ -16,12 +16,10 @@ package org.eclipse.jetty.websocket.api;
import java.time.Duration;
/**
- * Settings for WebSocket operations.
+ * Implementations allow to configure WebSocket parameters.
*/
-public interface WebSocketPolicy
+public interface Configurable
{
- WebSocketBehavior getBehavior();
-
/**
* The duration that a websocket may be idle before being closed by the implementation
*
@@ -29,6 +27,13 @@ public interface WebSocketPolicy
*/
Duration getIdleTimeout();
+ /**
+ * The duration that a websocket may be idle before being closed by the implementation
+ *
+ * @param duration the timeout duration (may not be null or negative)
+ */
+ void setIdleTimeout(Duration duration);
+
/**
* The input (read from network layer) buffer size.
*
@@ -39,6 +44,13 @@ public interface WebSocketPolicy
*/
int getInputBufferSize();
+ /**
+ * The input (read from network layer) buffer size.
+ *
+ * @param size the size in bytes
+ */
+ void setInputBufferSize(int size);
+
/**
* The output (write to network layer) buffer size.
*
@@ -49,6 +61,13 @@ public interface WebSocketPolicy
*/
int getOutputBufferSize();
+ /**
+ * The output (write to network layer) buffer size.
+ *
+ * @param size the size in bytes
+ */
+ void setOutputBufferSize(int size);
+
/**
* Get the maximum size of a binary message during parsing.
*
@@ -64,6 +83,16 @@ public interface WebSocketPolicy
*/
long getMaxBinaryMessageSize();
+ /**
+ * The maximum size of a binary message during parsing/generating.
+ *
+ * Binary messages over this maximum will result in a close code 1009 {@link StatusCode#MESSAGE_TOO_LARGE}
+ *
+ *
+ * @param size the maximum allowed size of a binary message.
+ */
+ void setMaxBinaryMessageSize(long size);
+
/**
* Get the maximum size of a text message during parsing.
*
@@ -79,51 +108,6 @@ public interface WebSocketPolicy
*/
long getMaxTextMessageSize();
- /**
- * The maximum payload size of any WebSocket Frame which can be received.
- *
- * @return the maximum size of a WebSocket Frame.
- */
- long getMaxFrameSize();
-
- /**
- * If true, frames are automatically fragmented to respect the maximum frame size.
- *
- * @return whether to automatically fragment incoming WebSocket Frames.
- */
- boolean isAutoFragment();
-
- /**
- * The duration that a websocket may be idle before being closed by the implementation
- *
- * @param duration the timeout duration (may not be null or negative)
- */
- void setIdleTimeout(Duration duration);
-
- /**
- * The input (read from network layer) buffer size.
- *
- * @param size the size in bytes
- */
- void setInputBufferSize(int size);
-
- /**
- * The output (write to network layer) buffer size.
- *
- * @param size the size in bytes
- */
- void setOutputBufferSize(int size);
-
- /**
- * The maximum size of a binary message during parsing/generating.
- *
- * Binary messages over this maximum will result in a close code 1009 {@link StatusCode#MESSAGE_TOO_LARGE}
- *
- *
- * @param size the maximum allowed size of a binary message.
- */
- void setMaxBinaryMessageSize(long size);
-
/**
* The maximum size of a text message during parsing/generating.
*
@@ -133,6 +117,13 @@ public interface WebSocketPolicy
*/
void setMaxTextMessageSize(long size);
+ /**
+ * The maximum payload size of any WebSocket Frame which can be received.
+ *
+ * @return the maximum size of a WebSocket Frame.
+ */
+ long getMaxFrameSize();
+
/**
* The maximum payload size of any WebSocket Frame which can be received.
*
@@ -143,10 +134,39 @@ public interface WebSocketPolicy
*/
void setMaxFrameSize(long maxFrameSize);
+ /**
+ * If true, frames are automatically fragmented to respect the maximum frame size.
+ *
+ * @return whether to automatically fragment incoming WebSocket Frames.
+ */
+ boolean isAutoFragment();
+
/**
* If set to true, frames are automatically fragmented to respect the maximum frame size.
*
* @param autoFragment whether to automatically fragment incoming WebSocket Frames.
*/
void setAutoFragment(boolean autoFragment);
+
+ /**
+ * Get the maximum number of data frames allowed to be waiting to be sent at any one time.
+ * The default value is -1, this indicates there is no limit on how many frames can be
+ * queued to be sent by the implementation. If the limit is exceeded, subsequent frames
+ * sent are failed with a {@link java.nio.channels.WritePendingException} but
+ * the connection is not failed and will remain open.
+ *
+ * @return the max number of frames.
+ */
+ int getMaxOutgoingFrames();
+
+ /**
+ * Set the maximum number of data frames allowed to be waiting to be sent at any one time.
+ * The default value is -1, this indicates there is no limit on how many frames can be
+ * queued to be sent by the implementation. If the limit is exceeded, subsequent frames
+ * sent are failed with a {@link java.nio.channels.WritePendingException} but
+ * the connection is not failed and will remain open.
+ *
+ * @param maxOutgoingFrames the max number of frames.
+ */
+ void setMaxOutgoingFrames(int maxOutgoingFrames);
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/RemoteEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/RemoteEndpoint.java
deleted file mode 100644
index 5800bc57892..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/RemoteEndpoint.java
+++ /dev/null
@@ -1,196 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-import java.io.IOException;
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-
-public interface RemoteEndpoint
-{
- /**
- * Send a binary message, returning when all bytes of the message has been transmitted.
- *
- * Note: this is a blocking call
- *
- * @param data the message to be sent
- * @throws IOException if unable to send the bytes
- */
- void sendBytes(ByteBuffer data) throws IOException;
-
- /**
- * Initiates the asynchronous transmission of a binary message. This method returns before the message is transmitted.
- * Developers may provide a callback to be notified when the message has been transmitted or resulted in an error.
- *
- * @param data the data being sent
- * @param callback callback to notify of success or failure of the write operation
- */
- void sendBytes(ByteBuffer data, WriteCallback callback);
-
- /**
- * Send a binary message in pieces, blocking until all of the message has been transmitted.
- * The runtime reads the message in order. Non-final pieces are
- * sent with isLast set to false. The final piece must be sent with isLast set to true.
- *
- * @param fragment the piece of the message being sent
- * @param isLast true if this is the last piece of the partial bytes
- * @throws IOException if unable to send the partial bytes
- */
- void sendPartialBytes(ByteBuffer fragment, boolean isLast) throws IOException;
-
- /**
- * Initiates the asynchronous transmission of a partial binary message. This method returns before the message is
- * transmitted.
- * The runtime reads the message in order. Non-final pieces are sent with isLast
- * set to false. The final piece must be sent with isLast set to true.
- * Developers may provide a callback to be notified when the message has been transmitted or resulted in an error.
- *
- * @param fragment the data being sent
- * @param isLast true if this is the last piece of the partial bytes
- * @param callback callback to notify of success or failure of the write operation
- */
- void sendPartialBytes(ByteBuffer fragment, boolean isLast, WriteCallback callback);
-
- /**
- * Send a text message, blocking until all bytes of the message has been transmitted.
- *
- * Note: this is a blocking call
- *
- * @param text the message to be sent
- * @throws IOException if unable to send the text message
- */
- void sendString(String text) throws IOException;
-
- /**
- * Initiates the asynchronous transmission of a text message. This method may return before the message is
- * transmitted. Developers may provide a callback to
- * be notified when the message has been transmitted or resulted in an error.
- *
- * @param text the text being sent
- * @param callback callback to notify of success or failure of the write operation
- */
- void sendString(String text, WriteCallback callback);
-
- /**
- * Send a text message in pieces, blocking until all of the message has been transmitted. The runtime reads the
- * message in order. Non-final pieces are sent
- * with isLast set to false. The final piece must be sent with isLast set to true.
- *
- * @param fragment the piece of the message being sent
- * @param isLast true if this is the last piece of the partial bytes
- * @throws IOException if unable to send the partial bytes
- */
- void sendPartialString(String fragment, boolean isLast) throws IOException;
-
- /**
- * Initiates the asynchronous transmission of a partial text message.
- * This method may return before the message is transmitted.
- * The runtime reads the message in order. Non-final pieces are sent with isLast
- * set to false. The final piece must be sent with isLast set to true.
- * Developers may provide a callback to be notified when the message has been transmitted or resulted in an error.
- *
- * @param fragment the text being sent
- * @param isLast true if this is the last piece of the partial bytes
- * @param callback callback to notify of success or failure of the write operation
- */
- void sendPartialString(String fragment, boolean isLast, WriteCallback callback);
-
- /**
- * Send a Ping message containing the given application data to the remote endpoint, blocking until all of the
- * message has been transmitted.
- * The corresponding Pong message may be picked up using the MessageHandler.Pong handler.
- *
- * @param applicationData the data to be carried in the ping request
- * @throws IOException if unable to send the ping
- */
- void sendPing(ByteBuffer applicationData) throws IOException;
-
- /**
- * Asynchronously send a Ping message containing the given application data to the remote endpoint.
- * The corresponding Pong message may be picked up using the MessageHandler.Pong handler.
- *
- * @param applicationData the data to be carried in the ping request
- * @param callback callback to notify of success or failure of the write operation
- */
- void sendPing(ByteBuffer applicationData, WriteCallback callback);
-
- /**
- * Allows the developer to send an unsolicited Pong message containing the given application data
- * in order to serve as a unidirectional heartbeat for the session, this will block until
- * all of the message has been transmitted.
- *
- * @param applicationData the application data to be carried in the pong response.
- * @throws IOException if unable to send the pong
- */
- void sendPong(ByteBuffer applicationData) throws IOException;
-
- /**
- * Allows the developer to asynchronously send an unsolicited Pong message containing the given application data
- * in order to serve as a unidirectional heartbeat for the session.
- *
- * @param applicationData the application data to be carried in the pong response.
- * @param callback callback to notify of success or failure of the write operation
- */
- void sendPong(ByteBuffer applicationData, WriteCallback callback);
-
- /**
- * @return the batch mode with which messages are sent.
- * @see #flush()
- */
- BatchMode getBatchMode();
-
- /**
- * Set the batch mode with which messages are sent.
- *
- * @param mode the batch mode to use
- * @see #flush()
- */
- void setBatchMode(BatchMode mode);
-
- /**
- * Get the maximum number of data frames allowed to be waiting to be sent at any one time.
- * The default value is -1, this indicates there is no limit on how many frames can be
- * queued to be sent by the implementation. If the limit is exceeded, subsequent frames
- * sent are failed with a {@link java.nio.channels.WritePendingException} but
- * the connection is not failed and will remain open.
- *
- * @return the max number of frames.
- */
- int getMaxOutgoingFrames();
-
- /**
- * Set the maximum number of data frames allowed to be waiting to be sent at any one time.
- * The default value is -1, this indicates there is no limit on how many frames can be
- * queued to be sent by the implementation. If the limit is exceeded, subsequent frames
- * sent are failed with a {@link java.nio.channels.WritePendingException} but
- * the connection is not failed and will remain open.
- *
- * @param maxOutgoingFrames the max number of frames.
- */
- void setMaxOutgoingFrames(int maxOutgoingFrames);
-
- /**
- * Get the SocketAddress for the established connection.
- *
- * @return the SocketAddress for the established connection.
- */
- SocketAddress getRemoteAddress();
-
- /**
- * Flushes messages that may have been batched by the implementation.
- *
- * @throws IOException if the flush fails
- */
- void flush() throws IOException;
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Session.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Session.java
index 3215c13577b..aba060cb4a3 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Session.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/Session.java
@@ -14,184 +14,349 @@
package org.eclipse.jetty.websocket.api;
import java.io.Closeable;
-import java.net.InetSocketAddress;
import java.net.SocketAddress;
+import java.nio.ByteBuffer;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
+import org.eclipse.jetty.websocket.api.annotations.WebSocket;
/**
- * Session represents an active link of communications with a Remote WebSocket Endpoint.
+ *
{@link Session} represents an active link of
+ * communication with a remote WebSocket endpoint.
+ * {@link Session} APIs can be used to configure
+ * the various parameters that control the behavior
+ * of the WebSocket communication, such as
+ * {@link #setMaxTextMessageSize(long)}, and to send
+ * WebSocket frames or messages to the other peer.
+ * The passive link of communication that receives
+ * WebSocket events is {@link Listener}.
*/
-public interface Session extends WebSocketPolicy, Closeable
+public interface Session extends Configurable, Closeable
{
/**
- * Request a close of the current conversation with a normal status code and no reason phrase.
- *
- * This will enqueue a graceful close to the remote endpoint.
+ *
Explicitly demands for WebSocket events.
+ * This method should be called only when the WebSocket endpoint is not
+ * demanding automatically, as defined by {@link WebSocket#autoDemand()}
+ * and {@link Listener.AutoDemanding}.
+ * In general, invoking this method results in a listener method or
+ * an annotated method to be called when the corresponding event is
+ * ready to be delivered.
+ * For WebSocket endpoints that wants to receive frame events
+ * (for example by overriding {@link Listener#onWebSocketFrame(Frame, Callback)}),
+ * invoking this method will result in a frame event being delivered to
+ * the listener/annotated method when a new frame is received.
+ * For WebSocket endpoints that want to receive whole message
+ * events (for example by overriding {@link Listener#onWebSocketText(String)}),
+ * invoking this method will result in a message event being delivered to
+ * the listener/annotated method when a new message is received.
+ * The implementation will automatically demand for more frames until a
+ * whole message is assembled and then deliver the whole message as event.
+ * Note that even when the WebSocket endpoint is interested in whole
+ * messages, calling this method is necessary not only to possibly receive
+ * the next whole message, but also to receive control frames (such as
+ * PING or CLOSE frames).
+ * Failing to call this method after receiving a whole message results
+ * in the CLOSE frame event to not be processed, and therefore for the
+ * endpoint to not notice when the other peer closed the WebSocket
+ * communication.
*
- * @see #close(CloseStatus)
- * @see #close(int, String)
+ * @throws IllegalStateException if the WebSocket endpoint is auto-demanding
+ */
+ void demand();
+
+ /**
+ * Initiates the asynchronous send of a BINARY message, notifying
+ * the given callback when the message send is completed, either
+ * successfully or with a failure.
+ *
+ * @param buffer the message bytes to send
+ * @param callback callback to notify when the send operation is complete
+ */
+ void sendBinary(ByteBuffer buffer, Callback callback);
+
+ /**
+ * Initiates the asynchronous send of a BINARY frame, possibly part
+ * of a larger binary message, notifying the given callback when the frame
+ * send is completed, either successfully or with a failure.
+ * Non-final frames must be sent with the parameter {@code last=false}.
+ * The final frame must be sent with {@code last=true}.
+ *
+ * @param buffer the frame bytes to send
+ * @param last whether this is the last frame of the message
+ * @param callback callback to notify when the send operation is complete
+ */
+ void sendPartialBinary(ByteBuffer buffer, boolean last, Callback callback);
+
+ /**
+ * Initiates the asynchronous send of a TEXT message, notifying
+ * the given callback when the message send is completed, either
+ * successfully or with a failure.
+ *
+ * @param text the message text to send
+ * @param callback callback to notify when the send operation is complete
+ */
+ void sendText(String text, Callback callback);
+
+ /**
+ * Initiates the asynchronous send of a TEXT frame, possibly part
+ * of a larger binary message, notifying the given callback when the frame
+ * send is completed, either successfully or with a failure.
+ * Non-final frames must be sent with the parameter {@code last=false}.
+ * The final frame must be sent with {@code last=true}.
+ *
+ * @param text the frame text to send
+ * @param last whether this is the last frame of the message
+ * @param callback callback to notify when the send operation is complete
+ */
+ void sendPartialText(String text, boolean last, Callback callback);
+
+ /**
+ * Initiates the asynchronous send of a PING frame, notifying the given
+ * callback when the frame send is completed, either successfully or with
+ * a failure.
+ *
+ * @param applicationData the data to be carried in the PING frame
+ * @param callback callback to notify when the send operation is complete
+ */
+ void sendPing(ByteBuffer applicationData, Callback callback);
+
+ /**
+ * Initiates the asynchronous send of a PONG frame, notifying the given
+ * callback when the frame send is completed, either successfully or with
+ * a failure.
+ *
+ * @param applicationData the data to be carried in the PONG frame
+ * @param callback callback to notify when the send operation is complete
+ */
+ void sendPong(ByteBuffer applicationData, Callback callback);
+
+ /**
+ * Equivalent to {@code close(StatusCode.NORMAL, null, Callback.NOOP)}.
+ *
+ * @see #close(int, String, Callback)
* @see #disconnect()
*/
@Override
- void close();
-
- /**
- * Request Close the current conversation, giving a reason for the closure. Note the websocket spec defines the acceptable uses of status codes and reason
- * phrases.
- *
- * This will enqueue a graceful close to the remote endpoint.
- *
- * @param closeStatus the reason for the closure
- * @see #close()
- * @see #close(int, String)
- * @see #disconnect()
- */
- void close(CloseStatus closeStatus);
-
- /**
- * Send a websocket Close frame, with status code.
- *
- * This will enqueue a graceful close to the remote endpoint.
- *
- * @param statusCode the status code
- * @param reason the (optional) reason. (can be null for no reason)
- * @see StatusCode
- * @see #close()
- * @see #close(CloseStatus)
- * @see #disconnect()
- */
- void close(int statusCode, String reason);
-
- /**
- * Send a websocket Close frame, with status code.
- *
- * This will enqueue a graceful close to the remote endpoint.
- *
- * @param statusCode the status code
- * @param reason the (optional) reason. (can be null for no reason)
- * @param callback the callback to track close frame sent (or failed)
- * @see StatusCode
- * @see #close()
- * @see #close(CloseStatus)
- * @see #disconnect()
- */
- default void close(int statusCode, String reason, WriteCallback callback)
+ default void close()
{
- try
- {
- close(statusCode, reason);
- callback.writeSuccess();
- }
- catch (Throwable t)
- {
- callback.writeFailed(t);
- }
+ close(StatusCode.NORMAL, null, Callback.NOOP);
}
/**
- * Issue a harsh disconnect of the underlying connection.
- *
- * This will terminate the connection, without sending a websocket close frame.
- *
- * Once called, any read/write activity on the websocket from this point will be indeterminate.
- *
- * Once the underlying connection has been determined to be closed, the various onClose() events (either
- * {@link WebSocketListener#onWebSocketClose(int, String)} or {@link OnWebSocketClose}) will be called on your
- * websocket.
+ *
Sends a websocket CLOSE frame, with status code and reason, notifying
+ * the given callback when the frame send is completed, either successfully
+ * or with a failure.
*
+ * @param statusCode the status code
+ * @param reason the (optional) reason
+ * @param callback callback to notify when the send operation is complete
+ * @see StatusCode
* @see #close()
- * @see #close(CloseStatus)
- * @see #close(int, String)
+ * @see #disconnect()
+ */
+ void close(int statusCode, String reason, Callback callback);
+
+ /**
+ * Abruptly closes the WebSocket connection without sending a CLOSE frame.
+ *
+ * @see #close(int, String, Callback)
*/
void disconnect();
/**
- * The Local Socket Address for the active Session
- *
- * Do not assume that this will return a {@link InetSocketAddress} in all cases.
- * Use of various proxies, and even UnixSockets can result a SocketAddress being returned
- * without supporting {@link InetSocketAddress}
- *
- *
- * @return the SocketAddress for the local connection, or null if not supported by Session
+ * @return the local SocketAddress for the connection, if available
*/
- SocketAddress getLocalAddress();
+ SocketAddress getLocalSocketAddress();
/**
- * Access the (now read-only) {@link WebSocketPolicy} in use for this connection.
- *
- * @return the policy in use
+ * @return the remote SocketAddress for the connection, if available
*/
- default WebSocketPolicy getPolicy()
- {
- return this;
- }
+ SocketAddress getRemoteSocketAddress();
/**
- * Returns the version of the websocket protocol currently being used. This is taken as the value of the Sec-WebSocket-Version header used in the opening
- * handshake. i.e. "13".
+ * Returns the version of the WebSocket protocol currently being used.
+ * This is taken as the value of the {@code Sec-WebSocket-Version} header
+ * used in the {@link #getUpgradeRequest() upgrade request}.
*
- * @return the protocol version
+ * @return the WebSocket protocol version
*/
String getProtocolVersion();
/**
- * Return a reference to the RemoteEndpoint object representing the other end of this conversation.
- *
- * @return the remote endpoint
- */
- RemoteEndpoint getRemote();
-
- /**
- * The Remote Socket Address for the active Session
- *
- * Do not assume that this will return a {@link InetSocketAddress} in all cases.
- * Use of various proxies, and even UnixSockets can result a SocketAddress being returned
- * without supporting {@link InetSocketAddress}
- *
- *
- * @return the SocketAddress for the remote connection, or null if not supported by Session
- */
- SocketAddress getRemoteAddress();
-
- /**
- * Get the UpgradeRequest used to create this session
- *
* @return the UpgradeRequest used to create this session
*/
UpgradeRequest getUpgradeRequest();
/**
- * Get the UpgradeResponse used to create this session
- *
* @return the UpgradeResponse used to create this session
*/
UpgradeResponse getUpgradeResponse();
/**
- * Return true if and only if the underlying socket is open.
- *
* @return whether the session is open
*/
boolean isOpen();
/**
- * Return true if and only if the underlying socket is using a secure transport.
- *
- * @return whether its using a secure transport
+ * @return whether the underlying socket is using a secure transport
*/
boolean isSecure();
/**
- * Suspend the delivery of incoming WebSocket frames.
- *
- * If this is called from inside the scope of the message handler the suspend takes effect immediately.
- * If suspend is called outside the scope of the message handler then the call may take effect
- * after 1 more frame is delivered.
- *
- *
- * @return the suspend token suitable for resuming the reading of data on the connection.
+ * The passive link of communication with a remote WebSocket endpoint.
+ * Applications provide WebSocket endpoints that implement this interface
+ * to receive WebSocket events from the remote peer, and can use
+ * {@link Session} for configuration and to send WebSocket frames or messages
+ * to the other peer.
*/
- SuspendToken suspend();
+ interface Listener
+ {
+ /**
+ * A WebSocket {@link Session} has opened successfully and is ready to be used.
+ * Applications can store the given {@link Session} as a field so it can be used
+ * to send messages back to the other peer.
+ *
+ * @param session the WebSocket session
+ */
+ default void onWebSocketOpen(Session session)
+ {
+ }
+
+ /**
+ * A WebSocket frame has been received.
+ * The received frames may be control frames such as PING, PONG or CLOSE,
+ * or data frames either BINARY or TEXT.
+ *
+ * @param frame the received frame
+ */
+ default void onWebSocketFrame(Frame frame, Callback callback)
+ {
+ }
+
+ /**
+ * A WebSocket PING frame has been received.
+ *
+ * @param payload the PING payload
+ */
+ default void onWebSocketPing(ByteBuffer payload)
+ {
+ }
+
+ /**
+ * A WebSocket PONG frame has been received.
+ *
+ * @param payload the PONG payload
+ */
+ default void onWebSocketPong(ByteBuffer payload)
+ {
+ }
+
+ /**
+ * A WebSocket BINARY (or associated CONTINUATION) frame has been received.
+ * The {@code ByteBuffer} is read-only, and will be recycled when the {@code callback}
+ * is completed.
+ *
+ * @param payload the BINARY frame payload
+ * @param last whether this is the last frame
+ * @param callback the callback to complete when the payload has been processed
+ */
+ default void onWebSocketPartialBinary(ByteBuffer payload, boolean last, Callback callback)
+ {
+ }
+
+ /**
+ * A WebSocket TEXT (or associated CONTINUATION) frame has been received.
+ *
+ * @param payload the text message payload
+ *
+ * Note that due to framing, there is a above average chance of any UTF8 sequences being split on the
+ * border between two frames will result in either the previous frame, or the next frame having an
+ * invalid UTF8 sequence, but the combined frames having a valid UTF8 sequence.
+ *
+ * The String being provided here will not end in a split UTF8 sequence. Instead this partial sequence
+ * will be held over until the next frame is received.
+ * @param last whether this is the last frame
+ */
+ default void onWebSocketPartialText(String payload, boolean last)
+ {
+ }
+
+ /**
+ *
A WebSocket BINARY message has been received.
+ *
+ * @param payload the raw payload array received
+ */
+ default void onWebSocketBinary(ByteBuffer payload, Callback callback)
+ {
+ }
+
+ /**
+ * A WebSocket TEXT message has been received.
+ *
+ * @param message the text payload
+ */
+ default void onWebSocketText(String message)
+ {
+ }
+
+ /**
+ * A WebSocket error has occurred during the processing of WebSocket frames.
+ * Usually errors occurs from bad or malformed incoming packets, for example
+ * text frames that do not contain UTF-8 bytes, frames that are too big, or other
+ * violations of the WebSocket specification.
+ * The WebSocket {@link Session} will be closed, but applications may
+ * explicitly {@link Session#close(int, String, Callback) close} the
+ * {@link Session} providing a different status code or reason.
+ *
+ * @param cause the error that occurred
+ */
+ default void onWebSocketError(Throwable cause)
+ {
+ }
+
+ /**
+ * The WebSocket {@link Session} has been closed.
+ *
+ * @param statusCode the close {@link StatusCode status code}
+ * @param reason the optional reason for the close
+ */
+ default void onWebSocketClose(int statusCode, String reason)
+ {
+ }
+
+ /**
+ * Tag interface that signals that the WebSocket endpoint
+ * is demanding for WebSocket frames automatically.
+ *
+ * @see WebSocket#autoDemand()
+ */
+ interface AutoDemanding extends Session.Listener
+ {
+ }
+
+ abstract class Abstract implements Listener
+ {
+ private volatile Session session;
+
+ @Override
+ public void onWebSocketOpen(Session session)
+ {
+ this.session = session;
+ }
+
+ public Session getSession()
+ {
+ return session;
+ }
+
+ public boolean isOpen()
+ {
+ Session session = this.session;
+ return session != null && session.isOpen();
+ }
+ }
+
+ abstract class AbstractAutoDemanding extends Abstract implements AutoDemanding
+ {
+ }
+ }
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/SuspendToken.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/SuspendToken.java
deleted file mode 100644
index 95d953a888a..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/SuspendToken.java
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-/**
- * Connection suspend token
- */
-public interface SuspendToken
-{
- /**
- * Resume a previously suspended connection.
- */
- void resume();
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketAdapter.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketAdapter.java
deleted file mode 100644
index 632b4970b90..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketAdapter.java
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-/**
- * Default implementation of the {@link WebSocketListener}.
- *
- * Convenient abstract class to base standard WebSocket implementations off of.
- */
-public class WebSocketAdapter implements WebSocketListener
-{
- private volatile Session session;
- private RemoteEndpoint remote;
-
- public RemoteEndpoint getRemote()
- {
- return remote;
- }
-
- public Session getSession()
- {
- return session;
- }
-
- public boolean isConnected()
- {
- Session sess = this.session;
- return (sess != null) && (sess.isOpen());
- }
-
- public boolean isNotConnected()
- {
- return !isConnected();
- }
-
- @Override
- public void onWebSocketBinary(byte[] payload, int offset, int len)
- {
- /* do nothing */
- }
-
- @Override
- public void onWebSocketClose(int statusCode, String reason)
- {
- /* do nothing */
- }
-
- @Override
- public void onWebSocketConnect(Session sess)
- {
- this.session = sess;
- this.remote = sess.getRemote();
- }
-
- @Override
- public void onWebSocketError(Throwable cause)
- {
- /* do nothing */
- }
-
- @Override
- public void onWebSocketText(String message)
- {
- /* do nothing */
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketBehavior.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketBehavior.java
deleted file mode 100644
index cf6dd8b743f..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketBehavior.java
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-/**
- * Behavior for how the WebSocket should operate.
- *
- * This dictated by the RFC 6455 spec in various places, where certain behavior must be performed depending on
- * operation as a CLIENT vs a SERVER
- */
-public enum WebSocketBehavior
-{
- CLIENT,
- SERVER
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnectionListener.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnectionListener.java
deleted file mode 100644
index 445900db064..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketConnectionListener.java
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-/**
- * Core WebSocket Connection Listener
- */
-public interface WebSocketConnectionListener
-{
- /**
- * A Close Event was received.
- *
- * The underlying Connection will be considered closed at this point.
- *
- * @param statusCode the close status code. (See {@link StatusCode})
- * @param reason the optional reason for the close.
- */
- default void onWebSocketClose(int statusCode, String reason)
- {
- }
-
- /**
- * A WebSocket {@link Session} has connected successfully and is ready to be used.
- *
- * Note: It is a good idea to track this session as a field in your object so that you can write messages back via the {@link RemoteEndpoint}
- *
- * @param session the websocket session.
- */
- default void onWebSocketConnect(Session session)
- {
- }
-
- /**
- * A WebSocket exception has occurred.
- *
- * This is a way for the internal implementation to notify of exceptions occured during the processing of websocket.
- *
- * Usually this occurs from bad / malformed incoming packets. (example: bad UTF8 data, frames that are too big, violations of the spec)
- *
- * This will result in the {@link Session} being closed by the implementing side.
- *
- * @param cause the error that occurred.
- */
- default void onWebSocketError(Throwable cause)
- {
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketFrameListener.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketFrameListener.java
deleted file mode 100644
index d61643a2d08..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketFrameListener.java
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-/**
- * WebSocket Frame Listener interface for incoming WebSocket frames.
- */
-public interface WebSocketFrameListener extends WebSocketConnectionListener
-{
- /**
- * A WebSocket frame has been received.
- *
- * @param frame the immutable frame received
- */
- void onWebSocketFrame(Frame frame);
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java
deleted file mode 100644
index 52869d0030d..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketListener.java
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-/**
- * Basic WebSocket Listener interface for incoming WebSocket message events.
- */
-public interface WebSocketListener extends WebSocketConnectionListener
-{
- /**
- * A WebSocket binary frame has been received.
- *
- * @param payload the raw payload array received
- * @param offset the offset in the payload array where the data starts
- * @param len the length of bytes in the payload
- */
- default void onWebSocketBinary(byte[] payload, int offset, int len)
- {
- }
-
- /**
- * A WebSocket Text frame was received.
- *
- * @param message the message
- */
- default void onWebSocketText(String message)
- {
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPartialListener.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPartialListener.java
deleted file mode 100644
index cd317e5aa2a..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPartialListener.java
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-import java.nio.ByteBuffer;
-
-/**
- * WebSocket Partial Message Listener interface for incoming WebSocket TEXT/BINARY/CONTINUATION frames.
- */
-public interface WebSocketPartialListener extends WebSocketConnectionListener
-{
- /**
- * A WebSocket BINARY (or associated CONTINUATION) frame has been received.
- *
- * Important Note: The payload {@code ByteBuffer} cannot be modified, and the ByteBuffer object itself
- * will be recycled on completion of this method call, make a copy of the data contained within if you want to
- * retain it between calls.
- *
- * @param payload the binary message frame payload
- * @param fin true if this is the final frame, false otherwise
- */
- default void onWebSocketPartialBinary(ByteBuffer payload, boolean fin)
- {
- }
-
- /**
- * A WebSocket TEXT (or associated CONTINUATION) frame has been received.
- *
- * @param payload the text message payload
- *
- * Note that due to framing, there is a above average chance of any UTF8 sequences being split on the
- * border between two frames will result in either the previous frame, or the next frame having an
- * invalid UTF8 sequence, but the combined frames having a valid UTF8 sequence.
- *
- * The String being provided here will not end in a split UTF8 sequence. Instead this partial sequence
- * will be held over until the next frame is received.
- * @param fin true if this is the final frame, false otherwise
- */
- default void onWebSocketPartialText(String payload, boolean fin)
- {
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPingPongListener.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPingPongListener.java
deleted file mode 100644
index f238c736e1e..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WebSocketPingPongListener.java
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-import java.nio.ByteBuffer;
-
-/**
- * WebSocket PING/PONG Listener interface for incoming WebSocket PING/PONG frames.
- */
-public interface WebSocketPingPongListener extends WebSocketConnectionListener
-{
- /**
- * A WebSocket PING has been received.
- *
- * @param payload the ping payload
- */
- default void onWebSocketPing(ByteBuffer payload)
- {
- }
-
- /**
- * A WebSocket PONG has been received.
- *
- * @param payload the pong payload
- */
- default void onWebSocketPong(ByteBuffer payload)
- {
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WriteCallback.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WriteCallback.java
deleted file mode 100644
index c66b40bdc21..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/WriteCallback.java
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.api;
-
-/**
- * Callback for Write events.
- *
- * NOTE: We don't expose org.eclipse.jetty.util.Callback here as that would complicate matters with the WebAppContext's classloader isolation.
- */
-public interface WriteCallback
-{
- WriteCallback NOOP = new WriteCallback()
- {
- };
-
- /**
- *
- * Callback invoked when the write fails.
- *
- *
- * @param x the reason for the write failure
- */
- default void writeFailed(Throwable x)
- {
- }
-
- /**
- *
- * Callback invoked when the write succeeds.
- *
- *
- * @see #writeFailed(Throwable)
- */
- default void writeSuccess()
- {
- }
-
- @Deprecated
- class Adaptor implements WriteCallback
- {
- @Override
- public void writeFailed(Throwable x)
- {
- }
-
- @Override
- public void writeSuccess()
- {
- }
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketClose.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketClose.java
index 214889dee79..5ffb023ee4b 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketClose.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketClose.java
@@ -19,23 +19,17 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.eclipse.jetty.websocket.api.Session;
-
/**
- * Annotation for tagging methods to receive connection close events.
- *
- * Acceptable method patterns.
- * Note: {@code methodName} can be any name you want to use.
+ *
Annotation for methods to receive WebSocket close events.
+ * Acceptable method patterns:
*
- * - {@code public void methodName(int statusCode, String reason)}
- * public void methodName({@link Session} session, int statusCode, String reason)
+ * - {@code public void (int statusCode, String reason)}
+ * - {@code public void (Session session, int statusCode, String reason)}
*
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target(value =
- {ElementType.METHOD})
+@Target(ElementType.METHOD)
public @interface OnWebSocketClose
{
- /* no config */
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketError.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketError.java
index ab59ebd9638..838397db217 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketError.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketError.java
@@ -19,23 +19,17 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.eclipse.jetty.websocket.api.Session;
-
/**
- * Annotation for receiving websocket errors (exceptions) that have occurred internally in the websocket implementation.
- *
- * Acceptable method patterns.
- * Note: {@code methodName} can be any name you want to use.
+ *
Annotation for methods to receive WebSocket errors.
+ * Acceptable method patterns:
*
- * public void methodName({@link Throwable} error)
- * public void methodName({@link Session} session, {@link Throwable} error)
+ * - {@code public void (Throwable cause)}
+ * - {@code public void (Session session, Throwable cause)}
*
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target(value =
- {ElementType.METHOD})
+@Target(ElementType.METHOD)
public @interface OnWebSocketError
{
- /* no config */
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketFrame.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketFrame.java
index 711e0a40e49..17a28bd9620 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketFrame.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketFrame.java
@@ -20,23 +20,20 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.eclipse.jetty.websocket.api.Frame;
-import org.eclipse.jetty.websocket.api.Session;
/**
- * (ADVANCED) Annotation for tagging methods to receive frame events.
- *
- * Acceptable method patterns.
- * Note: {@code methodName} can be any name you want to use.
+ *
Annotation for methods to receive WebSocket frame events.
+ * Acceptable method patterns:
*
- * public void methodName({@link Frame} frame)
- * public void methodName({@link Session} session, {@link Frame} frame)
+ * - {@code public void (Frame frame)}
+ * - {@code public void (Session session, Frame frame)}
*
+ *
+ * @see Frame
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target(value =
- {ElementType.METHOD})
+@Target(ElementType.METHOD)
public @interface OnWebSocketFrame
{
- /* no config */
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketMessage.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketMessage.java
index 71bb4a47232..2e7029aa779 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketMessage.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketMessage.java
@@ -13,6 +13,7 @@
package org.eclipse.jetty.websocket.api.annotations;
+import java.io.InputStream;
import java.io.Reader;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
@@ -20,15 +21,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
-
/**
- * Annotation for tagging methods to receive Binary or Text Message events.
- *
- * Acceptable method patterns.
- * Note: {@code methodName} can be any name you want to use.
- *
+ *
Annotation for methods to receive BINARY or TEXT WebSocket events.
+ * Acceptable method patterns:
* Text Message Versions
*
* - {@code public void methodName(String text)}
@@ -36,32 +31,38 @@ import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
* - {@code public void methodName(Reader reader)}
* - {@code public void methodName(Session session, Reader reader)}
*
- * Note: that the {@link Reader} in this case will always use UTF-8 encoding/charset (this is dictated by the RFC 6455 spec for Text Messages. If you need to
- * use a non-UTF-8 encoding/charset, you are instructed to use the binary messaging techniques.
+ * NOTE
+ * Method that takes a {@link Reader} must have
+ * {@link WebSocket#autoDemand()} set to {@code true}.
+ * NOTE
+ * The {@link Reader} argument will always use the UTF-8 charset,
+ * (as dictated by RFC 6455). If you need to use a different charset,
+ * you must use BINARY messages.
* Binary Message Versions
*
- * - {@code public void methodName(ByteBuffer message)}
- * - {@code public void methodName(Session session, ByteBuffer message)}
- * - {@code public void methodName(byte[] buf, int offset, int length)}
- * - {@code public void methodName(Session session, byte[] buf, int offset, int length)}
+ * - {@code public void methodName(ByteBuffer message, Callback callback)}
+ * - {@code public void methodName(Session session, ByteBuffer message, Callback callback)}
* - {@code public void methodName(InputStream stream)}
* - {@code public void methodName(Session session, InputStream stream)}
*
+ * NOTE
+ * Method that takes a {@link InputStream} must have
+ * {@link WebSocket#autoDemand()} set to {@code true}.
* Partial Message Variations
- * These are used to receive partial messages without aggregating them into a complete WebSocket message. Instead the a boolean
- * argument is supplied to indicate whether this is the last segment of data of the message. See {@link WebSocketPartialListener}
- * interface for more details on partial messages.
+ * These are used to receive individual frames (and therefore partial
+ * messages) without aggregating the frames into a complete WebSocket message.
+ * A {@code boolean} parameter is supplied to indicate whether the frame is
+ * the last segment of data of the message.
*
- * - {@code public void methodName(ByteBuffer payload, boolean last)}
+ * - {@code public void methodName(ByteBuffer payload, boolean last, Callback callback)}
+ * - {@code public void methodName(Session session, ByteBuffer payload, boolean last, Callback callback)}
* - {@code public void methodName(String payload, boolean last)}
+ * - {@code public void methodName(Session session, String payload, boolean last)}
*
- * Note: Similar to the signatures above these can all be used with an optional first {@link Session} parameter.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target(value =
- {ElementType.METHOD})
+@Target(ElementType.METHOD)
public @interface OnWebSocketMessage
{
- /* no config */
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketConnect.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketOpen.java
similarity index 68%
rename from jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketConnect.java
rename to jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketOpen.java
index 216f9ba8a13..722d0a3e097 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketConnect.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketOpen.java
@@ -19,22 +19,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.eclipse.jetty.websocket.api.Session;
-
/**
- * Annotation for tagging methods to receive connection open events.
- *
- * Only 1 acceptable method pattern for this annotation.
- * Note: {@code methodName} can be any name you want to use.
+ *
Annotation for methods to receive WebSocket connect events.
+ * Acceptable method patterns:
*
- * public void methodName({@link Session} session)
+ * - {@code public void (Session session)}
*
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target(value =
- {ElementType.METHOD})
-public @interface OnWebSocketConnect
+@Target(ElementType.METHOD)
+public @interface OnWebSocketOpen
{
- /* no config */
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/WebSocket.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/WebSocket.java
index 89bf5af750c..29f54f0b341 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/WebSocket.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/WebSocket.java
@@ -15,50 +15,31 @@ package org.eclipse.jetty.websocket.api.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.eclipse.jetty.websocket.api.BatchMode;
-import org.eclipse.jetty.websocket.api.StatusCode;
+import org.eclipse.jetty.websocket.api.Session;
/**
- * Tags a POJO as being a WebSocket class.
+ * Annotation for classes to be WebSocket endpoints.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target(value =
- {ElementType.TYPE})
+@Inherited
+@Target(value = ElementType.TYPE)
public @interface WebSocket
{
/**
- * The size of the buffer (in bytes) used to read from the network layer.
+ * Returns whether demand for WebSocket frames is automatically performed
+ * upon successful return from methods annotated with {@link OnWebSocketOpen},
+ * {@link OnWebSocketFrame} and {@link OnWebSocketMessage}.
+ * If the demand is not automatic, then {@link Session#demand()} must be
+ * explicitly invoked to receive more WebSocket frames (both control and
+ * data frames, including CLOSE frames).
+ *
+ * @return whether demand for WebSocket frames is automatic
*/
- int inputBufferSize() default -1;
-
- /**
- * The maximum size of a binary message (in bytes) during parsing/generating.
- *
- * Binary messages over this maximum will result in a close code 1009 {@link StatusCode#MESSAGE_TOO_LARGE}
- */
- int maxBinaryMessageSize() default -1;
-
- /**
- * The time in ms (milliseconds) that a websocket may be idle before closing.
- */
- int idleTimeout() default -1;
-
- /**
- * The maximum size of a text message during parsing/generating.
- *
- * Text messages over this maximum will result in a close code 1009 {@link StatusCode#MESSAGE_TOO_LARGE}
- */
- int maxTextMessageSize() default -1;
-
- /**
- * The output frame buffering mode.
- *
- * Default: {@link BatchMode#AUTO}
- */
- BatchMode batchMode() default BatchMode.AUTO;
+ boolean autoDemand() default true;
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/package-info.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/package-info.java
deleted file mode 100644
index bfd7fb65cde..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/package-info.java
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-/**
- * Jetty WebSocket API : WebSocket POJO Annotations
- */
-package org.eclipse.jetty.websocket.api.annotations;
-
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/exceptions/InvalidWebSocketException.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/exceptions/InvalidWebSocketException.java
index 247ed00f692..3d9680c4adb 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/exceptions/InvalidWebSocketException.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/exceptions/InvalidWebSocketException.java
@@ -13,8 +13,7 @@
package org.eclipse.jetty.websocket.api.exceptions;
-import org.eclipse.jetty.websocket.api.WebSocketAdapter;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
+import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
/**
@@ -22,12 +21,10 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket;
*
* A valid WebSocket should do one of the following:
*
- * - Implement {@link WebSocketListener}
- * - Extend {@link WebSocketAdapter}
+ * - Implement {@link Session.Listener}
* - Declare the {@link WebSocket @WebSocket} annotation on the type
*
*/
-@SuppressWarnings("serial")
public class InvalidWebSocketException extends WebSocketException
{
public InvalidWebSocketException(String message)
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/exceptions/package-info.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/exceptions/package-info.java
deleted file mode 100644
index 94b0379a261..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/exceptions/package-info.java
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-/**
- * Jetty WebSocket API : Exception Types
- */
-package org.eclipse.jetty.websocket.api.exceptions;
-
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/package-info.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/package-info.java
deleted file mode 100644
index 4579e7bf04f..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-api/src/main/java/org/eclipse/jetty/websocket/api/package-info.java
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-/**
- * Jetty WebSocket API
- */
-package org.eclipse.jetty.websocket.api;
-
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java
index 0b3071684c1..2d2105e94ac 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java
@@ -35,10 +35,9 @@ import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Graceful;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ShutdownThread;
+import org.eclipse.jetty.websocket.api.Configurable;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketContainer;
-import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
import org.eclipse.jetty.websocket.client.internal.JettyClientUpgradeRequest;
import org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandler;
@@ -52,7 +51,7 @@ import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class WebSocketClient extends ContainerLifeCycle implements WebSocketPolicy, WebSocketContainer
+public class WebSocketClient extends ContainerLifeCycle implements Configurable, WebSocketContainer
{
private static final Logger LOG = LoggerFactory.getLogger(WebSocketClient.class);
private final WebSocketCoreClient coreClient;
@@ -177,12 +176,6 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketPoli
dumpObjects(out, indent, getOpenSessions());
}
- @Override
- public WebSocketBehavior getBehavior()
- {
- return WebSocketBehavior.CLIENT;
- }
-
@Override
public void addSessionListener(WebSocketSessionListener listener)
{
@@ -217,42 +210,6 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketPoli
return configurationCustomizer.getIdleTimeout();
}
- @Override
- public int getInputBufferSize()
- {
- return configurationCustomizer.getInputBufferSize();
- }
-
- @Override
- public int getOutputBufferSize()
- {
- return configurationCustomizer.getOutputBufferSize();
- }
-
- @Override
- public long getMaxBinaryMessageSize()
- {
- return configurationCustomizer.getMaxBinaryMessageSize();
- }
-
- @Override
- public long getMaxTextMessageSize()
- {
- return configurationCustomizer.getMaxTextMessageSize();
- }
-
- @Override
- public long getMaxFrameSize()
- {
- return configurationCustomizer.getMaxFrameSize();
- }
-
- @Override
- public boolean isAutoFragment()
- {
- return configurationCustomizer.isAutoFragment();
- }
-
@Override
public void setIdleTimeout(Duration duration)
{
@@ -260,42 +217,90 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketPoli
getHttpClient().setIdleTimeout(duration.toMillis());
}
+ @Override
+ public int getInputBufferSize()
+ {
+ return configurationCustomizer.getInputBufferSize();
+ }
+
@Override
public void setInputBufferSize(int size)
{
configurationCustomizer.setInputBufferSize(size);
}
+ @Override
+ public int getOutputBufferSize()
+ {
+ return configurationCustomizer.getOutputBufferSize();
+ }
+
@Override
public void setOutputBufferSize(int size)
{
configurationCustomizer.setOutputBufferSize(size);
}
+ @Override
+ public long getMaxBinaryMessageSize()
+ {
+ return configurationCustomizer.getMaxBinaryMessageSize();
+ }
+
@Override
public void setMaxBinaryMessageSize(long size)
{
configurationCustomizer.setMaxBinaryMessageSize(size);
}
+ @Override
+ public long getMaxTextMessageSize()
+ {
+ return configurationCustomizer.getMaxTextMessageSize();
+ }
+
@Override
public void setMaxTextMessageSize(long size)
{
configurationCustomizer.setMaxTextMessageSize(size);
}
+ @Override
+ public long getMaxFrameSize()
+ {
+ return configurationCustomizer.getMaxFrameSize();
+ }
+
@Override
public void setMaxFrameSize(long maxFrameSize)
{
configurationCustomizer.setMaxFrameSize(maxFrameSize);
}
+ @Override
+ public boolean isAutoFragment()
+ {
+ return configurationCustomizer.isAutoFragment();
+ }
+
@Override
public void setAutoFragment(boolean autoFragment)
{
configurationCustomizer.setAutoFragment(autoFragment);
}
+ @Override
+ public int getMaxOutgoingFrames()
+ {
+ return configurationCustomizer.getMaxOutgoingFrames();
+ }
+
+ @Override
+ public void setMaxOutgoingFrames(int maxOutgoingFrames)
+ {
+ configurationCustomizer.setMaxOutgoingFrames(maxOutgoingFrames);
+ }
+
public SocketAddress getBindAddress()
{
return getHttpClient().getBindAddress();
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/examples/ClientDemo.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/examples/ClientDemo.java
index 1f35d5174a6..6ff57fc3152 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/examples/ClientDemo.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/examples/ClientDemo.java
@@ -24,7 +24,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.core.OpCode;
@@ -37,26 +36,13 @@ import org.eclipse.jetty.websocket.core.OpCode;
*/
public class ClientDemo
{
- public class TestSocket extends WebSocketAdapter
+ public class TestSocket extends Session.Listener.Abstract
{
@Override
- public void onWebSocketBinary(byte[] payload, int offset, int len)
- {
- }
-
- @Override
- public void onWebSocketClose(int statusCode, String reason)
- {
- super.onWebSocketClose(statusCode, reason);
- }
-
- @Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
if (verbose)
- {
- System.err.printf("%s#onWebSocketConnect %s %s\n", this.getClass().getSimpleName(), session, session.getClass().getSimpleName());
- }
+ System.err.printf("%s#onWebSocketOpen %s %s\n", this.getClass().getSimpleName(), session, session.getClass().getSimpleName());
}
public void send(byte op, byte[] data, int maxFragmentLength)
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/examples/SimpleEchoSocket.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/examples/SimpleEchoSocket.java
index 5a843c54dfe..9c8a40090cf 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/examples/SimpleEchoSocket.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/examples/SimpleEchoSocket.java
@@ -16,22 +16,21 @@ package examples;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
/**
* Basic Echo Client Socket
*/
-@WebSocket(maxTextMessageSize = 64 * 1024)
+@WebSocket
public class SimpleEchoSocket
{
private final CountDownLatch closeLatch;
- @SuppressWarnings("unused")
- private Session session;
public SimpleEchoSocket()
{
@@ -47,20 +46,19 @@ public class SimpleEchoSocket
public void onClose(int statusCode, String reason)
{
System.out.printf("Connection closed: %d - %s%n", statusCode, reason);
- this.session = null;
this.closeLatch.countDown(); // trigger latch
}
- @OnWebSocketConnect
- public void onConnect(Session session)
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
- System.out.printf("Got connect: %s%n", session);
- this.session = session;
+ System.out.printf("Open: %s%n", session);
+ session.setMaxTextMessageSize(64 * 1024);
try
{
- session.getRemote().sendString("Hello");
- session.getRemote().sendString("Thanks for the conversation.");
- session.close(StatusCode.NORMAL, "I'm done");
+ session.sendText("Hello", Callback.NOOP);
+ session.sendText("Thanks for the conversation.", Callback.NOOP);
+ session.close(StatusCode.NORMAL, "I'm done", Callback.NOOP);
}
catch (Throwable t)
{
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientBadUriTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientBadUriTest.java
index b6d982161a9..b15a09a59fe 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientBadUriTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientBadUriTest.java
@@ -19,7 +19,7 @@ import java.util.stream.Stream;
import org.eclipse.jetty.toolchain.test.jupiter.TestTrackerExtension;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -40,7 +40,7 @@ public class WebSocketClientBadUriTest
{
public CountDownLatch openLatch = new CountDownLatch(1);
- @OnWebSocketConnect
+ @OnWebSocketOpen
public void onOpen(Session session)
{
openLatch.countDown();
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandler.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandler.java
index e777fd9778f..9d9665dd49a 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandler.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandler.java
@@ -14,21 +14,20 @@
package org.eclipse.jetty.websocket.common;
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
-import java.util.concurrent.Executor;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
-import org.eclipse.jetty.util.thread.AutoLock;
-import org.eclipse.jetty.websocket.api.BatchMode;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.api.WebSocketContainer;
-import org.eclipse.jetty.websocket.api.WriteCallback;
import org.eclipse.jetty.websocket.core.CloseStatus;
-import org.eclipse.jetty.websocket.core.Configuration;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.FrameHandler;
@@ -48,71 +47,45 @@ import org.slf4j.LoggerFactory;
public class JettyWebSocketFrameHandler implements FrameHandler
{
- private enum SuspendState
- {
- DEMANDING,
- SUSPENDING,
- SUSPENDED,
- CLOSED
- }
-
- private final AutoLock lock = new AutoLock();
+ private final AtomicBoolean closeNotified = new AtomicBoolean();
private final Logger log;
private final WebSocketContainer container;
private final Object endpointInstance;
- private final BatchMode batchMode;
- private final AtomicBoolean closeNotified = new AtomicBoolean();
+ private final JettyWebSocketFrameHandlerMetadata metadata;
private MethodHandle openHandle;
private MethodHandle closeHandle;
private MethodHandle errorHandle;
private MethodHandle textHandle;
- private final Class extends MessageSink> textSinkClass;
private MethodHandle binaryHandle;
+ private final Class extends MessageSink> textSinkClass;
private final Class extends MessageSink> binarySinkClass;
private MethodHandle frameHandle;
private MethodHandle pingHandle;
private MethodHandle pongHandle;
private UpgradeRequest upgradeRequest;
private UpgradeResponse upgradeResponse;
-
- private final Configuration.Customizer customizer;
private MessageSink textSink;
private MessageSink binarySink;
private MessageSink activeMessageSink;
private WebSocketSession session;
- private SuspendState state = SuspendState.DEMANDING;
- private Runnable delayedOnFrame;
- private CoreSession coreSession;
- public JettyWebSocketFrameHandler(WebSocketContainer container,
- Object endpointInstance,
- MethodHandle openHandle, MethodHandle closeHandle, MethodHandle errorHandle,
- MethodHandle textHandle, MethodHandle binaryHandle,
- Class extends MessageSink> textSinkClass,
- Class extends MessageSink> binarySinkClass,
- MethodHandle frameHandle,
- MethodHandle pingHandle, MethodHandle pongHandle,
- BatchMode batchMode,
- Configuration.Customizer customizer)
+ public JettyWebSocketFrameHandler(WebSocketContainer container, Object endpointInstance, JettyWebSocketFrameHandlerMetadata metadata)
{
this.log = LoggerFactory.getLogger(endpointInstance.getClass());
-
this.container = container;
this.endpointInstance = endpointInstance;
+ this.metadata = metadata;
- this.openHandle = openHandle;
- this.closeHandle = closeHandle;
- this.errorHandle = errorHandle;
- this.textHandle = textHandle;
- this.binaryHandle = binaryHandle;
- this.textSinkClass = textSinkClass;
- this.binarySinkClass = binarySinkClass;
- this.frameHandle = frameHandle;
- this.pingHandle = pingHandle;
- this.pongHandle = pongHandle;
-
- this.batchMode = batchMode;
- this.customizer = customizer;
+ this.openHandle = InvokerUtils.bindTo(metadata.getOpenHandle(), endpointInstance);
+ this.closeHandle = InvokerUtils.bindTo(metadata.getCloseHandle(), endpointInstance);
+ this.errorHandle = InvokerUtils.bindTo(metadata.getErrorHandle(), endpointInstance);
+ this.textHandle = InvokerUtils.bindTo(metadata.getTextHandle(), endpointInstance);
+ this.binaryHandle = InvokerUtils.bindTo(metadata.getBinaryHandle(), endpointInstance);
+ this.textSinkClass = metadata.getTextSink();
+ this.binarySinkClass = metadata.getBinarySink();
+ this.frameHandle = InvokerUtils.bindTo(metadata.getFrameHandle(), endpointInstance);
+ this.pingHandle = InvokerUtils.bindTo(metadata.getPingHandle(), endpointInstance);
+ this.pongHandle = InvokerUtils.bindTo(metadata.getPongHandle(), endpointInstance);
}
public void setUpgradeRequest(UpgradeRequest upgradeRequest)
@@ -135,11 +108,6 @@ public class JettyWebSocketFrameHandler implements FrameHandler
return upgradeResponse;
}
- public BatchMode getBatchMode()
- {
- return batchMode;
- }
-
public WebSocketSession getSession()
{
return session;
@@ -150,8 +118,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
{
try
{
- customizer.customize(coreSession);
- this.coreSession = coreSession;
+ metadata.customize(coreSession);
session = new WebSocketSession(container, coreSession, this);
if (!session.isOpen())
throw new IllegalStateException("Session is not open");
@@ -165,13 +132,11 @@ public class JettyWebSocketFrameHandler implements FrameHandler
pingHandle = InvokerUtils.bindTo(pingHandle, session);
pongHandle = InvokerUtils.bindTo(pongHandle, session);
- Executor executor = container.getExecutor();
-
if (textHandle != null)
- textSink = JettyWebSocketFrameHandlerFactory.createMessageSink(textHandle, textSinkClass, executor, session);
+ textSink = createMessageSink(textSinkClass, session, textHandle, isAutoDemand());
if (binaryHandle != null)
- binarySink = JettyWebSocketFrameHandlerFactory.createMessageSink(binaryHandle, binarySinkClass, executor, session);
+ binarySink = createMessageSink(binarySinkClass, session, binaryHandle, isAutoDemand());
if (openHandle != null)
openHandle.invoke();
@@ -180,74 +145,90 @@ public class JettyWebSocketFrameHandler implements FrameHandler
container.notifySessionListeners((listener) -> listener.onWebSocketSessionOpened(session));
callback.succeeded();
- demand();
}
catch (Throwable cause)
{
callback.failed(new WebSocketException(endpointInstance.getClass().getSimpleName() + " OPEN method error: " + cause.getMessage(), cause));
}
+ finally
+ {
+ autoDemand();
+ }
+ }
+
+ private static MessageSink createMessageSink(Class extends MessageSink> sinkClass, WebSocketSession session, MethodHandle msgHandle, boolean autoDemanding)
+ {
+ if (msgHandle == null)
+ return null;
+ if (sinkClass == null)
+ return null;
+
+ try
+ {
+ MethodHandles.Lookup lookup = JettyWebSocketFrameHandlerFactory.getServerMethodHandleLookup();
+ MethodHandle ctorHandle = lookup.findConstructor(sinkClass,
+ MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, boolean.class));
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgHandle, autoDemanding);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new RuntimeException("Missing expected MessageSink constructor found at: " + sinkClass.getName(), e);
+ }
+ catch (IllegalAccessException | InstantiationException | InvocationTargetException e)
+ {
+ throw new RuntimeException("Unable to create MessageSink: " + sinkClass.getName(), e);
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Throwable t)
+ {
+ throw new RuntimeException(t);
+ }
}
@Override
- public void onFrame(Frame frame, Callback callback)
+ public void onFrame(Frame frame, Callback coreCallback)
{
- try (AutoLock l = lock.lock())
- {
- switch (state)
- {
- case DEMANDING:
- break;
-
- case SUSPENDING:
- delayedOnFrame = () -> onFrame(frame, callback);
- state = SuspendState.SUSPENDED;
- return;
-
- default:
- throw new IllegalStateException();
- }
-
- // If we have received a close frame, set state to closed to disallow further suspends and resumes.
- if (frame.getOpCode() == OpCode.CLOSE)
- state = SuspendState.CLOSED;
- }
-
- // Send to raw frame handling on user side (eg: WebSocketFrameListener)
+ CompletableFuture frameCallback = null;
if (frameHandle != null)
{
try
{
- frameHandle.invoke(new JettyWebSocketFrame(frame));
+ frameCallback = new org.eclipse.jetty.websocket.api.Callback.Completable();
+ frameHandle.invoke(new JettyWebSocketFrame(frame), frameCallback);
}
catch (Throwable cause)
{
- throw new WebSocketException(endpointInstance.getClass().getSimpleName() + " FRAME method error: " + cause.getMessage(), cause);
+ coreCallback.failed(new WebSocketException(endpointInstance.getClass().getSimpleName() + " FRAME method error: " + cause.getMessage(), cause));
+ return;
}
}
+ Callback.Completable eventCallback = new Callback.Completable();
switch (frame.getOpCode())
{
- case OpCode.CLOSE:
- onCloseFrame(frame, callback);
- break;
- case OpCode.PING:
- onPingFrame(frame, callback);
- break;
- case OpCode.PONG:
- onPongFrame(frame, callback);
- break;
- case OpCode.TEXT:
- onTextFrame(frame, callback);
- break;
- case OpCode.BINARY:
- onBinaryFrame(frame, callback);
- break;
- case OpCode.CONTINUATION:
- onContinuationFrame(frame, callback);
- break;
- default:
- callback.failed(new IllegalStateException());
- }
+ case OpCode.CLOSE -> onCloseFrame(frame, eventCallback);
+ case OpCode.PING -> onPingFrame(frame, eventCallback);
+ case OpCode.PONG -> onPongFrame(frame, eventCallback);
+ case OpCode.TEXT -> onTextFrame(frame, eventCallback);
+ case OpCode.BINARY -> onBinaryFrame(frame, eventCallback);
+ case OpCode.CONTINUATION -> onContinuationFrame(frame, eventCallback);
+ default -> coreCallback.failed(new IllegalStateException());
+ };
+
+ // Combine the callback from the frame handler and the event handler.
+ CompletableFuture callback = eventCallback;
+ if (frameCallback != null)
+ callback = frameCallback.thenCompose(ignored -> eventCallback);
+ callback.whenComplete((r, x) ->
+ {
+ if (x == null)
+ coreCallback.succeeded();
+ else
+ coreCallback.failed(x);
+ });
}
@Override
@@ -257,11 +238,13 @@ public class JettyWebSocketFrameHandler implements FrameHandler
{
cause = convertCause(cause);
if (errorHandle != null)
+ {
errorHandle.invoke(cause);
+ }
else
{
if (log.isDebugEnabled())
- log.warn("Unhandled Error: Endpoint {}", endpointInstance.getClass().getName(), cause);
+ log.debug("Unhandled Error: Endpoint {}", endpointInstance.getClass().getName(), cause);
else
log.warn("Unhandled Error: Endpoint {} : {}", endpointInstance.getClass().getName(), cause.toString());
}
@@ -275,24 +258,18 @@ public class JettyWebSocketFrameHandler implements FrameHandler
}
}
- private void onCloseFrame(Frame frame, Callback callback)
- {
- notifyOnClose(CloseStatus.getCloseStatus(frame), callback);
- }
-
@Override
public void onClosed(CloseStatus closeStatus, Callback callback)
{
- try (AutoLock l = lock.lock())
- {
- // We are now closed and cannot suspend or resume.
- state = SuspendState.CLOSED;
- }
-
notifyOnClose(closeStatus, callback);
container.notifySessionListeners((listener) -> listener.onWebSocketSessionClosed(session));
}
+ private void onCloseFrame(Frame frame, Callback callback)
+ {
+ notifyOnClose(CloseStatus.getCloseStatus(frame), callback);
+ }
+
private void notifyOnClose(CloseStatus closeStatus, Callback callback)
{
// Make sure onClose is only notified once.
@@ -306,7 +283,6 @@ public class JettyWebSocketFrameHandler implements FrameHandler
{
if (closeHandle != null)
closeHandle.invoke(closeStatus.getCode(), closeStatus.getReason());
-
callback.succeeded();
}
catch (Throwable cause)
@@ -315,40 +291,6 @@ public class JettyWebSocketFrameHandler implements FrameHandler
}
}
- public String toString()
- {
- return String.format("%s@%x[%s]", this.getClass().getSimpleName(), this.hashCode(), endpointInstance.getClass().getName());
- }
-
- private void acceptMessage(Frame frame, Callback callback)
- {
- // No message sink is active
- if (activeMessageSink == null)
- {
- callback.succeeded();
- demand();
- return;
- }
-
- // Accept the payload into the message sink
- activeMessageSink.accept(frame, callback);
- if (frame.isFin())
- activeMessageSink = null;
- }
-
- private void onBinaryFrame(Frame frame, Callback callback)
- {
- if (activeMessageSink == null)
- activeMessageSink = binarySink;
-
- acceptMessage(frame, callback);
- }
-
- private void onContinuationFrame(Frame frame, Callback callback)
- {
- acceptMessage(frame, callback);
- }
-
private void onPingFrame(Frame frame, Callback callback)
{
if (pingHandle != null)
@@ -358,35 +300,34 @@ public class JettyWebSocketFrameHandler implements FrameHandler
ByteBuffer payload = frame.getPayload();
if (payload == null)
payload = BufferUtil.EMPTY_BUFFER;
-
+ else
+ payload = BufferUtil.copy(payload);
pingHandle.invoke(payload);
+ callback.succeeded();
+ autoDemand();
}
catch (Throwable cause)
{
- throw new WebSocketException(endpointInstance.getClass().getSimpleName() + " PING method error: " + cause.getMessage(), cause);
+ callback.failed(new WebSocketException(endpointInstance.getClass().getSimpleName() + " PING method error: " + cause.getMessage(), cause));
}
-
- callback.succeeded();
- demand();
}
else
{
// Automatically respond.
- getSession().getRemote().sendPong(frame.getPayload(), new WriteCallback()
+ getSession().sendPong(frame.getPayload(), new org.eclipse.jetty.websocket.api.Callback()
{
@Override
- public void writeSuccess()
+ public void succeed()
{
callback.succeeded();
- demand();
+ autoDemand();
}
@Override
- public void writeFailed(Throwable x)
+ public void fail(Throwable x)
{
- // Ignore failures, we might be output closed and receive ping.
+ // Ignore failures, we might be output closed and receive a PING.
callback.succeeded();
- demand();
}
});
}
@@ -401,111 +342,74 @@ public class JettyWebSocketFrameHandler implements FrameHandler
ByteBuffer payload = frame.getPayload();
if (payload == null)
payload = BufferUtil.EMPTY_BUFFER;
-
+ else
+ payload = BufferUtil.copy(payload);
pongHandle.invoke(payload);
+ callback.succeeded();
+ autoDemand();
}
catch (Throwable cause)
{
- throw new WebSocketException(endpointInstance.getClass().getSimpleName() + " PONG method error: " + cause.getMessage(), cause);
+ callback.failed(new WebSocketException(endpointInstance.getClass().getSimpleName() + " PONG method error: " + cause.getMessage(), cause));
}
}
-
- callback.succeeded();
- demand();
+ else
+ {
+ autoDemand();
+ }
}
private void onTextFrame(Frame frame, Callback callback)
{
if (activeMessageSink == null)
activeMessageSink = textSink;
-
- acceptMessage(frame, callback);
+ acceptFrame(frame, callback);
}
- @Override
- public boolean isAutoDemanding()
+ private void onBinaryFrame(Frame frame, Callback callback)
{
- return false;
+ if (activeMessageSink == null)
+ activeMessageSink = binarySink;
+ acceptFrame(frame, callback);
}
- public void suspend()
+ private void onContinuationFrame(Frame frame, Callback callback)
{
- try (AutoLock l = lock.lock())
- {
- switch (state)
- {
- case DEMANDING:
- state = SuspendState.SUSPENDING;
- break;
-
- default:
- throw new IllegalStateException(state.name());
- }
- }
+ acceptFrame(frame, callback);
}
- public void resume()
+ private void acceptFrame(Frame frame, Callback callback)
{
- boolean needDemand = false;
- Runnable delayedFrame = null;
- try (AutoLock l = lock.lock())
+ // No message sink is active.
+ if (activeMessageSink == null)
{
- switch (state)
- {
- case DEMANDING:
- throw new IllegalStateException("Already Resumed");
-
- case SUSPENDED:
- needDemand = true;
- delayedFrame = delayedOnFrame;
- delayedOnFrame = null;
- state = SuspendState.DEMANDING;
- break;
-
- case SUSPENDING:
- if (delayedOnFrame != null)
- throw new IllegalStateException();
- state = SuspendState.DEMANDING;
- break;
-
- default:
- throw new IllegalStateException(state.name());
- }
+ callback.succeeded();
+ autoDemand();
+ return;
}
- if (needDemand)
- {
- if (delayedFrame != null)
- delayedFrame.run();
- else
- session.getCoreSession().demand(1);
- }
+ // Accept the payload into the message sink.
+ activeMessageSink.accept(frame, callback);
+ if (frame.isFin())
+ activeMessageSink = null;
}
- private void demand()
+ boolean isAutoDemand()
{
- boolean demand = false;
- try (AutoLock l = lock.lock())
- {
- switch (state)
- {
- case DEMANDING:
- demand = true;
- break;
+ return metadata.isAutoDemand();
+ }
- case SUSPENDING:
- state = SuspendState.SUSPENDED;
- break;
-
- default:
- throw new IllegalStateException(state.name());
- }
- }
-
- if (demand)
+ private void autoDemand()
+ {
+ if (isAutoDemand())
session.getCoreSession().demand(1);
}
+ public String toString()
+ {
+ return String.format("%s@%x[%s]", this.getClass().getSimpleName(), this.hashCode(), endpointInstance.getClass().getName());
+ }
+
public static Throwable convertCause(Throwable cause)
{
if (cause instanceof MessageTooLargeException)
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerFactory.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerFactory.java
index db85ec467a1..aa010794a53 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerFactory.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerFactory.java
@@ -19,41 +19,29 @@ import java.io.Reader;
import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
-import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executor;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
-import org.eclipse.jetty.websocket.api.BatchMode;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Frame;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketConnectionListener;
import org.eclipse.jetty.websocket.api.WebSocketContainer;
-import org.eclipse.jetty.websocket.api.WebSocketFrameListener;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
-import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
-import org.eclipse.jetty.websocket.api.WebSocketPingPongListener;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
-import org.eclipse.jetty.websocket.core.CoreSession;
+import org.eclipse.jetty.websocket.api.exceptions.InvalidWebSocketException;
+import org.eclipse.jetty.websocket.common.internal.ByteBufferMessageSink;
+import org.eclipse.jetty.websocket.common.internal.PartialByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
-import org.eclipse.jetty.websocket.core.exception.InvalidWebSocketException;
-import org.eclipse.jetty.websocket.core.messages.ByteArrayMessageSink;
-import org.eclipse.jetty.websocket.core.messages.ByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
-import org.eclipse.jetty.websocket.core.messages.MessageSink;
-import org.eclipse.jetty.websocket.core.messages.PartialByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialStringMessageSink;
import org.eclipse.jetty.websocket.core.messages.ReaderMessageSink;
import org.eclipse.jetty.websocket.core.messages.StringMessageSink;
@@ -68,12 +56,7 @@ import org.eclipse.jetty.websocket.core.util.ReflectUtils;
*
*
* - Is @{@link org.eclipse.jetty.websocket.api.annotations.WebSocket} annotated
- * - Extends {@link org.eclipse.jetty.websocket.api.WebSocketAdapter}
- * - Implements {@link org.eclipse.jetty.websocket.api.WebSocketListener}
- * - Implements {@link org.eclipse.jetty.websocket.api.WebSocketConnectionListener}
- * - Implements {@link org.eclipse.jetty.websocket.api.WebSocketPartialListener}
- * - Implements {@link org.eclipse.jetty.websocket.api.WebSocketPingPongListener}
- * - Implements {@link org.eclipse.jetty.websocket.api.WebSocketFrameListener}
+ * - Implements {@link org.eclipse.jetty.websocket.api.Session.Listener}
*
*/
public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
@@ -85,14 +68,8 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
private static final InvokerUtils.Arg[] binaryBufferCallingArgs = new InvokerUtils.Arg[]{
new InvokerUtils.Arg(Session.class),
- new InvokerUtils.Arg(ByteBuffer.class).required()
- };
-
- private static final InvokerUtils.Arg[] binaryArrayCallingArgs = new InvokerUtils.Arg[]{
- new InvokerUtils.Arg(Session.class),
- new InvokerUtils.Arg(byte[].class).required(),
- new InvokerUtils.Arg(int.class), // offset
- new InvokerUtils.Arg(int.class) // length
+ new InvokerUtils.Arg(ByteBuffer.class).required(),
+ new InvokerUtils.Arg(Callback.class).required()
};
private static final InvokerUtils.Arg[] inputStreamCallingArgs = new InvokerUtils.Arg[]{
@@ -114,13 +91,8 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
private static final InvokerUtils.Arg[] binaryPartialBufferCallingArgs = new InvokerUtils.Arg[]{
new InvokerUtils.Arg(Session.class),
new InvokerUtils.Arg(ByteBuffer.class).required(),
- new InvokerUtils.Arg(boolean.class).required()
- };
-
- private static final InvokerUtils.Arg[] binaryPartialArrayCallingArgs = new InvokerUtils.Arg[]{
- new InvokerUtils.Arg(Session.class),
- new InvokerUtils.Arg(byte[].class).required(),
- new InvokerUtils.Arg(boolean.class).required()
+ new InvokerUtils.Arg(boolean.class).required(),
+ new InvokerUtils.Arg(Callback.class).required()
};
private final WebSocketContainer container;
@@ -153,16 +125,12 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
public JettyWebSocketFrameHandlerMetadata createMetadata(Class> endpointClass)
{
- if (WebSocketConnectionListener.class.isAssignableFrom(endpointClass))
- {
+ if (Session.Listener.class.isAssignableFrom(endpointClass))
return createListenerMetadata(endpointClass);
- }
WebSocket websocket = endpointClass.getAnnotation(WebSocket.class);
if (websocket != null)
- {
return createAnnotatedMetadata(websocket, endpointClass);
- }
throw new InvalidWebSocketException("Unrecognized WebSocket endpoint: " + endpointClass.getName());
}
@@ -171,62 +139,10 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
{
JettyWebSocketFrameHandlerMetadata metadata = getMetadata(endpointInstance.getClass());
- final MethodHandle openHandle = InvokerUtils.bindTo(metadata.getOpenHandle(), endpointInstance);
- final MethodHandle closeHandle = InvokerUtils.bindTo(metadata.getCloseHandle(), endpointInstance);
- final MethodHandle errorHandle = InvokerUtils.bindTo(metadata.getErrorHandle(), endpointInstance);
- final MethodHandle textHandle = InvokerUtils.bindTo(metadata.getTextHandle(), endpointInstance);
- final MethodHandle binaryHandle = InvokerUtils.bindTo(metadata.getBinaryHandle(), endpointInstance);
- final Class extends MessageSink> textSinkClass = metadata.getTextSink();
- final Class extends MessageSink> binarySinkClass = metadata.getBinarySink();
- final MethodHandle frameHandle = InvokerUtils.bindTo(metadata.getFrameHandle(), endpointInstance);
- final MethodHandle pingHandle = InvokerUtils.bindTo(metadata.getPingHandle(), endpointInstance);
- final MethodHandle pongHandle = InvokerUtils.bindTo(metadata.getPongHandle(), endpointInstance);
- BatchMode batchMode = metadata.getBatchMode();
-
// Decorate the endpointInstance while we are still upgrading for access to things like HttpSession.
components.getObjectFactory().decorate(endpointInstance);
- return new JettyWebSocketFrameHandler(
- container,
- endpointInstance,
- openHandle, closeHandle, errorHandle,
- textHandle, binaryHandle,
- textSinkClass, binarySinkClass,
- frameHandle, pingHandle, pongHandle,
- batchMode,
- metadata);
- }
-
- public static MessageSink createMessageSink(MethodHandle msgHandle, Class extends MessageSink> sinkClass, Executor executor, WebSocketSession session)
- {
- if (msgHandle == null)
- return null;
- if (sinkClass == null)
- return null;
-
- try
- {
- MethodHandles.Lookup lookup = JettyWebSocketFrameHandlerFactory.getServerMethodHandleLookup();
- MethodHandle ctorHandle = lookup.findConstructor(sinkClass,
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class));
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgHandle);
- }
- catch (NoSuchMethodException e)
- {
- throw new RuntimeException("Missing expected MessageSink constructor found at: " + sinkClass.getName(), e);
- }
- catch (IllegalAccessException | InstantiationException | InvocationTargetException e)
- {
- throw new RuntimeException("Unable to create MessageSink: " + sinkClass.getName(), e);
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Throwable t)
- {
- throw new RuntimeException(t);
- }
+ return new JettyWebSocketFrameHandler(container, endpointInstance, metadata);
}
private MethodHandle toMethodHandle(MethodHandles.Lookup lookup, Method method)
@@ -244,99 +160,121 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
private JettyWebSocketFrameHandlerMetadata createListenerMetadata(Class> endpointClass)
{
JettyWebSocketFrameHandlerMetadata metadata = new JettyWebSocketFrameHandlerMetadata();
+ metadata.setAutoDemand(Session.Listener.AutoDemanding.class.isAssignableFrom(endpointClass));
+
MethodHandles.Lookup lookup = JettyWebSocketFrameHandlerFactory.getServerMethodHandleLookup();
- if (!WebSocketConnectionListener.class.isAssignableFrom(endpointClass))
- throw new IllegalArgumentException("Class " + endpointClass + " does not implement " + WebSocketConnectionListener.class);
-
- Method openMethod = ReflectUtils.findMethod(WebSocketConnectionListener.class, "onWebSocketConnect", Session.class);
- MethodHandle open = toMethodHandle(lookup, openMethod);
- metadata.setOpenHandler(open, openMethod);
-
- Method closeMethod = ReflectUtils.findMethod(WebSocketConnectionListener.class, "onWebSocketClose", int.class, String.class);
- MethodHandle close = toMethodHandle(lookup, closeMethod);
- metadata.setCloseHandler(close, closeMethod);
-
- Method errorMethod = ReflectUtils.findMethod(WebSocketConnectionListener.class, "onWebSocketError", Throwable.class);
- MethodHandle error = toMethodHandle(lookup, errorMethod);
- metadata.setErrorHandler(error, errorMethod);
-
- // Simple Data Listener
- if (WebSocketListener.class.isAssignableFrom(endpointClass))
+ Method openMethod = findMethod(endpointClass, "onWebSocketOpen", Session.class);
+ if (openMethod != null)
{
- Method textMethod = ReflectUtils.findMethod(WebSocketListener.class, "onWebSocketText", String.class);
- MethodHandle text = toMethodHandle(lookup, textMethod);
- metadata.setTextHandler(StringMessageSink.class, text, textMethod);
-
- Method binaryMethod = ReflectUtils.findMethod(WebSocketListener.class, "onWebSocketBinary", byte[].class, int.class, int.class);
- MethodHandle binary = toMethodHandle(lookup, binaryMethod);
- metadata.setBinaryHandle(ByteArrayMessageSink.class, binary, binaryMethod);
+ MethodHandle connectHandle = toMethodHandle(lookup, openMethod);
+ metadata.setOpenHandle(connectHandle, openMethod);
}
- // Ping/Pong Listener
- if (WebSocketPingPongListener.class.isAssignableFrom(endpointClass))
+ Method frameMethod = findMethod(endpointClass, "onWebSocketFrame", Frame.class, Callback.class);
+ if (frameMethod != null)
{
- Method pongMethod = ReflectUtils.findMethod(WebSocketPingPongListener.class, "onWebSocketPong", ByteBuffer.class);
- MethodHandle pong = toMethodHandle(lookup, pongMethod);
- metadata.setPongHandle(pong, pongMethod);
-
- Method pingMethod = ReflectUtils.findMethod(WebSocketPingPongListener.class, "onWebSocketPing", ByteBuffer.class);
- MethodHandle ping = toMethodHandle(lookup, pingMethod);
- metadata.setPingHandle(ping, pingMethod);
+ MethodHandle frameHandle = toMethodHandle(lookup, frameMethod);
+ metadata.setFrameHandle(frameHandle, frameMethod);
}
- // Partial Data / Message Listener
- if (WebSocketPartialListener.class.isAssignableFrom(endpointClass))
+ Method pingMethod = findMethod(endpointClass, "onWebSocketPing", ByteBuffer.class);
+ if (pingMethod != null)
{
- Method textMethod = ReflectUtils.findMethod(WebSocketPartialListener.class, "onWebSocketPartialText", String.class, boolean.class);
- MethodHandle text = toMethodHandle(lookup, textMethod);
- metadata.setTextHandler(PartialStringMessageSink.class, text, textMethod);
-
- Method binaryMethod = ReflectUtils.findMethod(WebSocketPartialListener.class, "onWebSocketPartialBinary", ByteBuffer.class, boolean.class);
- MethodHandle binary = toMethodHandle(lookup, binaryMethod);
- metadata.setBinaryHandle(PartialByteBufferMessageSink.class, binary, binaryMethod);
+ MethodHandle pingHandle = toMethodHandle(lookup, pingMethod);
+ metadata.setPingHandle(pingHandle, pingMethod);
}
- // Frame Listener
- if (WebSocketFrameListener.class.isAssignableFrom(endpointClass))
+ Method pongMethod = findMethod(endpointClass, "onWebSocketPong", ByteBuffer.class);
+ if (pongMethod != null)
{
- Method frameMethod = ReflectUtils.findMethod(WebSocketFrameListener.class, "onWebSocketFrame", Frame.class);
- MethodHandle frame = toMethodHandle(lookup, frameMethod);
- metadata.setFrameHandler(frame, frameMethod);
+ MethodHandle pongHandle = toMethodHandle(lookup, pongMethod);
+ metadata.setPongHandle(pongHandle, pongMethod);
+ }
+
+ Method partialTextMethod = findMethod(endpointClass, "onWebSocketPartialText", String.class, boolean.class);
+ if (partialTextMethod != null)
+ {
+ MethodHandle partialTextHandle = toMethodHandle(lookup, partialTextMethod);
+ metadata.setTextHandle(PartialStringMessageSink.class, partialTextHandle, partialTextMethod);
+ }
+
+ Method partialBinaryMethod = findMethod(endpointClass, "onWebSocketPartialBinary", ByteBuffer.class, boolean.class, Callback.class);
+ if (partialBinaryMethod != null)
+ {
+ MethodHandle partialBinaryHandle = toMethodHandle(lookup, partialBinaryMethod);
+ metadata.setBinaryHandle(PartialByteBufferMessageSink.class, partialBinaryHandle, partialBinaryMethod);
+ }
+
+ Method textMethod = findMethod(endpointClass, "onWebSocketText", String.class);
+ if (textMethod != null)
+ {
+ MethodHandle textHandle = toMethodHandle(lookup, textMethod);
+ metadata.setTextHandle(StringMessageSink.class, textHandle, textMethod);
+ }
+
+ Method binaryMethod = findMethod(endpointClass, "onWebSocketBinary", ByteBuffer.class, Callback.class);
+ if (binaryMethod != null)
+ {
+ MethodHandle binaryHandle = toMethodHandle(lookup, binaryMethod);
+ metadata.setBinaryHandle(ByteBufferMessageSink.class, binaryHandle, binaryMethod);
+ }
+
+ Method errorMethod = findMethod(endpointClass, "onWebSocketError", Throwable.class);
+ if (errorMethod != null)
+ {
+ MethodHandle errorHandle = toMethodHandle(lookup, errorMethod);
+ metadata.setErrorHandle(errorHandle, errorMethod);
+ }
+
+ Method closeMethod = findMethod(endpointClass, "onWebSocketClose", int.class, String.class);
+ if (closeMethod != null)
+ {
+ MethodHandle closeHandle = toMethodHandle(lookup, closeMethod);
+ metadata.setCloseHandle(closeHandle, closeMethod);
}
return metadata;
}
+ private Method findMethod(Class> klass, String name, Class>... parameters)
+ {
+ // Verify if the method is overridden in the endpoint class, to avoid
+ // calling all methods of Session.Listener even if they are not overridden.
+ Method method = ReflectUtils.findMethod(klass, name, parameters);
+ if (method == null)
+ return null;
+ if (!isOverridden(method))
+ return null;
+ // The method is overridden, but it may be declared in a non-public
+ // class, for example an anonymous class, where it won't be accessible,
+ // therefore replace it with the accessible version from Session.Listener.
+ if (!Modifier.isPublic(klass.getModifiers()))
+ method = ReflectUtils.findMethod(Session.Listener.class, name, parameters);
+ return method;
+ }
+
+ private boolean isOverridden(Method method)
+ {
+ return method != null && method.getDeclaringClass() != Session.Listener.class;
+ }
+
private JettyWebSocketFrameHandlerMetadata createAnnotatedMetadata(WebSocket anno, Class> endpointClass)
{
JettyWebSocketFrameHandlerMetadata metadata = new JettyWebSocketFrameHandlerMetadata();
-
- int max = anno.inputBufferSize();
- if (max >= 0)
- metadata.setInputBufferSize(max);
- max = anno.maxBinaryMessageSize();
- if (max >= 0)
- metadata.setMaxBinaryMessageSize(max);
- max = anno.maxTextMessageSize();
- if (max >= 0)
- metadata.setMaxTextMessageSize(max);
- max = anno.idleTimeout();
- if (max >= 0)
- metadata.setIdleTimeout(Duration.ofMillis(max));
- metadata.setBatchMode(anno.batchMode());
+ metadata.setAutoDemand(anno.autoDemand());
MethodHandles.Lookup lookup = getApplicationMethodHandleLookup(endpointClass);
Method onmethod;
- // OnWebSocketConnect [0..1]
- onmethod = ReflectUtils.findAnnotatedMethod(endpointClass, OnWebSocketConnect.class);
+ // OnWebSocketOpen [0..1]
+ onmethod = ReflectUtils.findAnnotatedMethod(endpointClass, OnWebSocketOpen.class);
if (onmethod != null)
{
- assertSignatureValid(endpointClass, onmethod, OnWebSocketConnect.class);
+ assertSignatureValid(endpointClass, onmethod, OnWebSocketOpen.class);
final InvokerUtils.Arg SESSION = new InvokerUtils.Arg(Session.class).required();
MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, endpointClass, onmethod, SESSION);
- metadata.setOpenHandler(methodHandle, onmethod);
+ metadata.setOpenHandle(methodHandle, onmethod);
}
// OnWebSocketClose [0..1]
@@ -348,7 +286,7 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
final InvokerUtils.Arg STATUS_CODE = new InvokerUtils.Arg(int.class);
final InvokerUtils.Arg REASON = new InvokerUtils.Arg(String.class);
MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, endpointClass, onmethod, SESSION, STATUS_CODE, REASON);
- metadata.setCloseHandler(methodHandle, onmethod);
+ metadata.setCloseHandle(methodHandle, onmethod);
}
// OnWebSocketError [0..1]
@@ -359,7 +297,7 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
final InvokerUtils.Arg SESSION = new InvokerUtils.Arg(Session.class);
final InvokerUtils.Arg CAUSE = new InvokerUtils.Arg(Throwable.class).required();
MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, endpointClass, onmethod, SESSION, CAUSE);
- metadata.setErrorHandler(methodHandle, onmethod);
+ metadata.setErrorHandle(methodHandle, onmethod);
}
// OnWebSocketFrame [0..1]
@@ -369,13 +307,14 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
assertSignatureValid(endpointClass, onmethod, OnWebSocketFrame.class);
final InvokerUtils.Arg SESSION = new InvokerUtils.Arg(Session.class);
final InvokerUtils.Arg FRAME = new InvokerUtils.Arg(Frame.class).required();
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, endpointClass, onmethod, SESSION, FRAME);
- metadata.setFrameHandler(methodHandle, onmethod);
+ final InvokerUtils.Arg CALLBACK = new InvokerUtils.Arg(Callback.class).required();
+ MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, endpointClass, onmethod, SESSION, FRAME, CALLBACK);
+ metadata.setFrameHandle(methodHandle, onmethod);
}
// OnWebSocketMessage [0..2]
Method[] onMessages = ReflectUtils.findAnnotatedMethods(endpointClass, OnWebSocketMessage.class);
- if (onMessages != null && onMessages.length > 0)
+ if (onMessages != null)
{
// The different kind of @OnWebSocketMessage method parameter signatures expected
for (Method onMsg : onMessages)
@@ -387,7 +326,7 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
{
// Normal Text Message
assertSignatureValid(endpointClass, onMsg, OnWebSocketMessage.class);
- metadata.setTextHandler(StringMessageSink.class, methodHandle, onMsg);
+ metadata.setTextHandle(StringMessageSink.class, methodHandle, onMsg);
continue;
}
@@ -400,18 +339,12 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
continue;
}
- methodHandle = InvokerUtils.optionalMutatedInvoker(lookup, endpointClass, onMsg, binaryArrayCallingArgs);
- if (methodHandle != null)
- {
- // byte[] Binary Message
- assertSignatureValid(endpointClass, onMsg, OnWebSocketMessage.class);
- metadata.setBinaryHandle(ByteArrayMessageSink.class, methodHandle, onMsg);
- continue;
- }
-
methodHandle = InvokerUtils.optionalMutatedInvoker(lookup, endpointClass, onMsg, inputStreamCallingArgs);
if (methodHandle != null)
{
+ if (!metadata.isAutoDemand())
+ throw new InvalidWebSocketException("InputStream methods require auto-demanding WebSocket endpoints");
+
// InputStream Binary Message
assertSignatureValid(endpointClass, onMsg, OnWebSocketMessage.class);
metadata.setBinaryHandle(InputStreamMessageSink.class, methodHandle, onMsg);
@@ -421,9 +354,12 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
methodHandle = InvokerUtils.optionalMutatedInvoker(lookup, endpointClass, onMsg, readerCallingArgs);
if (methodHandle != null)
{
+ if (!metadata.isAutoDemand())
+ throw new InvalidWebSocketException("Reader methods require auto-demanding WebSocket endpoints");
+
// Reader Text Message
assertSignatureValid(endpointClass, onMsg, OnWebSocketMessage.class);
- metadata.setTextHandler(ReaderMessageSink.class, methodHandle, onMsg);
+ metadata.setTextHandle(ReaderMessageSink.class, methodHandle, onMsg);
continue;
}
@@ -432,7 +368,7 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
{
// Partial Text Message
assertSignatureValid(endpointClass, onMsg, OnWebSocketMessage.class);
- metadata.setTextHandler(PartialStringMessageSink.class, methodHandle, onMsg);
+ metadata.setTextHandle(PartialStringMessageSink.class, methodHandle, onMsg);
continue;
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerMetadata.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerMetadata.java
index db2f617971e..0a5009558f8 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerMetadata.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerMetadata.java
@@ -15,38 +15,32 @@ package org.eclipse.jetty.websocket.common;
import java.lang.invoke.MethodHandle;
-import org.eclipse.jetty.websocket.api.BatchMode;
import org.eclipse.jetty.websocket.api.exceptions.InvalidWebSocketException;
import org.eclipse.jetty.websocket.core.Configuration;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
public class JettyWebSocketFrameHandlerMetadata extends Configuration.ConfigurationCustomizer
{
+ private boolean autoDemand;
private MethodHandle openHandle;
private MethodHandle closeHandle;
private MethodHandle errorHandle;
-
private MethodHandle frameHandle;
-
private MethodHandle textHandle;
private Class extends MessageSink> textSink;
private MethodHandle binaryHandle;
private Class extends MessageSink> binarySink;
-
private MethodHandle pingHandle;
private MethodHandle pongHandle;
- // Batch Configuration
- private BatchMode batchMode = BatchMode.OFF;
-
- public void setBatchMode(BatchMode batchMode)
+ public boolean isAutoDemand()
{
- this.batchMode = batchMode;
+ return autoDemand;
}
- public BatchMode getBatchMode()
+ public void setAutoDemand(boolean autoDemand)
{
- return batchMode;
+ this.autoDemand = autoDemand;
}
public void setBinaryHandle(Class extends MessageSink> sinkClass, MethodHandle binary, Object origin)
@@ -66,7 +60,7 @@ public class JettyWebSocketFrameHandlerMetadata extends Configuration.Configurat
return binarySink;
}
- public void setCloseHandler(MethodHandle close, Object origin)
+ public void setCloseHandle(MethodHandle close, Object origin)
{
assertNotSet(this.closeHandle, "CLOSE Handler", origin);
this.closeHandle = close;
@@ -77,7 +71,7 @@ public class JettyWebSocketFrameHandlerMetadata extends Configuration.Configurat
return closeHandle;
}
- public void setErrorHandler(MethodHandle error, Object origin)
+ public void setErrorHandle(MethodHandle error, Object origin)
{
assertNotSet(this.errorHandle, "ERROR Handler", origin);
this.errorHandle = error;
@@ -88,7 +82,7 @@ public class JettyWebSocketFrameHandlerMetadata extends Configuration.Configurat
return errorHandle;
}
- public void setFrameHandler(MethodHandle frame, Object origin)
+ public void setFrameHandle(MethodHandle frame, Object origin)
{
assertNotSet(this.frameHandle, "FRAME Handler", origin);
this.frameHandle = frame;
@@ -99,10 +93,10 @@ public class JettyWebSocketFrameHandlerMetadata extends Configuration.Configurat
return frameHandle;
}
- public void setOpenHandler(MethodHandle open, Object origin)
+ public void setOpenHandle(MethodHandle openHandle, Object origin)
{
assertNotSet(this.openHandle, "OPEN Handler", origin);
- this.openHandle = open;
+ this.openHandle = openHandle;
}
public MethodHandle getOpenHandle()
@@ -132,7 +126,7 @@ public class JettyWebSocketFrameHandlerMetadata extends Configuration.Configurat
return pongHandle;
}
- public void setTextHandler(Class extends MessageSink> sinkClass, MethodHandle text, Object origin)
+ public void setTextHandle(Class extends MessageSink> sinkClass, MethodHandle text, Object origin)
{
assertNotSet(this.textHandle, "TEXT Handler", origin);
this.textHandle = text;
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketRemoteEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketRemoteEndpoint.java
deleted file mode 100644
index 3db93a71fcb..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketRemoteEndpoint.java
+++ /dev/null
@@ -1,235 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.common;
-
-import java.io.IOException;
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-import java.util.Objects;
-
-import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.Callback;
-import org.eclipse.jetty.util.FutureCallback;
-import org.eclipse.jetty.websocket.api.BatchMode;
-import org.eclipse.jetty.websocket.api.WriteCallback;
-import org.eclipse.jetty.websocket.core.CoreSession;
-import org.eclipse.jetty.websocket.core.Frame;
-import org.eclipse.jetty.websocket.core.OpCode;
-import org.eclipse.jetty.websocket.core.exception.ProtocolException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-public class JettyWebSocketRemoteEndpoint implements org.eclipse.jetty.websocket.api.RemoteEndpoint
-{
- private static final Logger LOG = LoggerFactory.getLogger(JettyWebSocketRemoteEndpoint.class);
-
- private final CoreSession coreSession;
- private byte messageType = -1;
- private BatchMode batchMode;
-
- public JettyWebSocketRemoteEndpoint(CoreSession coreSession, BatchMode batchMode)
- {
- this.coreSession = Objects.requireNonNull(coreSession);
- this.batchMode = batchMode;
- }
-
- @Override
- public void sendString(String text) throws IOException
- {
- sendBlocking(new Frame(OpCode.TEXT).setPayload(text));
- }
-
- @Override
- public void sendString(String text, WriteCallback callback)
- {
- Callback cb = callback == null ? Callback.NOOP : Callback.from(callback::writeSuccess, callback::writeFailed);
- coreSession.sendFrame(new Frame(OpCode.TEXT).setPayload(text), cb, isBatch());
- }
-
- @Override
- public void sendBytes(ByteBuffer data) throws IOException
- {
- sendBlocking(new Frame(OpCode.BINARY).setPayload(data));
- }
-
- @Override
- public void sendBytes(ByteBuffer data, WriteCallback callback)
- {
- coreSession.sendFrame(new Frame(OpCode.BINARY).setPayload(data),
- Callback.from(callback::writeSuccess, callback::writeFailed),
- isBatch());
- }
-
- @Override
- public void sendPartialBytes(ByteBuffer fragment, boolean isLast) throws IOException
- {
- FutureCallback b = new FutureCallback();
- sendPartialBytes(fragment, isLast, b);
- b.block();
- }
-
- @Override
- public void sendPartialBytes(ByteBuffer fragment, boolean isLast, WriteCallback callback)
- {
- sendPartialBytes(fragment, isLast, Callback.from(callback::writeSuccess, callback::writeFailed));
- }
-
- private void sendPartialBytes(ByteBuffer fragment, boolean isLast, Callback callback)
- {
- Frame frame;
- switch (messageType)
- {
- case -1: // new message
- frame = new Frame(OpCode.BINARY);
- messageType = OpCode.BINARY;
- break;
- case OpCode.BINARY:
- frame = new Frame(OpCode.CONTINUATION);
- break;
- default:
- callback.failed(new ProtocolException("Attempt to send Partial Binary during active opcode " + messageType));
- return;
- }
-
- frame.setPayload(fragment);
- frame.setFin(isLast);
-
- coreSession.sendFrame(frame, callback, isBatch());
-
- if (isLast)
- {
- messageType = -1;
- }
- }
-
- @Override
- public void sendPartialString(String fragment, boolean isLast) throws IOException
- {
- FutureCallback b = new FutureCallback();
- sendPartialText(fragment, isLast, b);
- b.block();
- }
-
- @Override
- public void sendPartialString(String fragment, boolean isLast, WriteCallback callback)
- {
- sendPartialText(fragment, isLast, Callback.from(callback::writeSuccess, callback::writeFailed));
- }
-
- @Override
- public void sendPing(ByteBuffer applicationData) throws IOException
- {
- sendBlocking(new Frame(OpCode.PING).setPayload(applicationData));
- }
-
- @Override
- public void sendPing(ByteBuffer applicationData, WriteCallback callback)
- {
- coreSession.sendFrame(new Frame(OpCode.PING).setPayload(applicationData),
- Callback.from(callback::writeSuccess, callback::writeFailed), false);
- }
-
- @Override
- public void sendPong(ByteBuffer applicationData) throws IOException
- {
- sendBlocking(new Frame(OpCode.PONG).setPayload(applicationData));
- }
-
- @Override
- public void sendPong(ByteBuffer applicationData, WriteCallback callback)
- {
- coreSession.sendFrame(new Frame(OpCode.PONG).setPayload(applicationData),
- Callback.from(callback::writeSuccess, callback::writeFailed), false);
- }
-
- private void sendPartialText(String fragment, boolean isLast, Callback callback)
- {
- Frame frame;
- switch (messageType)
- {
- case -1: // new message
- frame = new Frame(OpCode.TEXT);
- messageType = OpCode.TEXT;
- break;
- case OpCode.TEXT:
- frame = new Frame(OpCode.CONTINUATION);
- break;
- default:
- callback.failed(new ProtocolException("Attempt to send Partial Text during active opcode " + messageType));
- return;
- }
-
- frame.setPayload(BufferUtil.toBuffer(fragment, UTF_8));
- frame.setFin(isLast);
-
- coreSession.sendFrame(frame, callback, isBatch());
-
- if (isLast)
- {
- messageType = -1;
- }
- }
-
- private void sendBlocking(Frame frame) throws IOException
- {
- FutureCallback b = new FutureCallback();
- coreSession.sendFrame(frame, b, false);
- b.block();
- }
-
- @Override
- public BatchMode getBatchMode()
- {
- return batchMode;
- }
-
- @Override
- public void setBatchMode(BatchMode mode)
- {
- batchMode = mode;
- }
-
- @Override
- public int getMaxOutgoingFrames()
- {
- return coreSession.getMaxOutgoingFrames();
- }
-
- @Override
- public void setMaxOutgoingFrames(int maxOutgoingFrames)
- {
- coreSession.setMaxOutgoingFrames(maxOutgoingFrames);
- }
-
- private boolean isBatch()
- {
- return BatchMode.ON == batchMode;
- }
-
- @Override
- public SocketAddress getRemoteAddress()
- {
- return coreSession.getRemoteAddress();
- }
-
- @Override
- public void flush() throws IOException
- {
- FutureCallback b = new FutureCallback();
- coreSession.flush(b);
- b.block();
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/SessionTracker.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/SessionTracker.java
index 2868c656c82..23447fc5c09 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/SessionTracker.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/SessionTracker.java
@@ -24,6 +24,7 @@ import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.Graceful;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
@@ -76,7 +77,7 @@ public class SessionTracker extends AbstractLifeCycle implements WebSocketSessio
break;
// SHUTDOWN is abnormal close status so it will hard close connection after sent.
- session.close(StatusCode.SHUTDOWN, "Container being shut down");
+ session.close(StatusCode.SHUTDOWN, "Container being shut down", Callback.NOOP);
}
});
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java
index f3bf94fc4b2..8999602a90d 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java
@@ -15,29 +15,31 @@ package org.eclipse.jetty.websocket.common;
import java.io.IOException;
import java.net.SocketAddress;
+import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.Objects;
-import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.component.Dumpable;
-import org.eclipse.jetty.websocket.api.CloseStatus;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.api.SuspendToken;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
-import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketContainer;
-import org.eclipse.jetty.websocket.api.WriteCallback;
import org.eclipse.jetty.websocket.core.CoreSession;
+import org.eclipse.jetty.websocket.core.Frame;
+import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.exception.ProtocolException;
-public class WebSocketSession implements Session, SuspendToken, Dumpable
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class WebSocketSession implements Session, Dumpable
{
private final CoreSession coreSession;
private final JettyWebSocketFrameHandler frameHandler;
- private final JettyWebSocketRemoteEndpoint remoteEndpoint;
private final UpgradeRequest upgradeRequest;
private final UpgradeResponse upgradeResponse;
+ private byte messageType = OpCode.UNDEFINED;
public WebSocketSession(WebSocketContainer container, CoreSession coreSession, JettyWebSocketFrameHandler frameHandler)
{
@@ -45,126 +47,197 @@ public class WebSocketSession implements Session, SuspendToken, Dumpable
this.coreSession = Objects.requireNonNull(coreSession);
this.upgradeRequest = frameHandler.getUpgradeRequest();
this.upgradeResponse = frameHandler.getUpgradeResponse();
- this.remoteEndpoint = new JettyWebSocketRemoteEndpoint(coreSession, frameHandler.getBatchMode());
container.notifySessionListeners((listener) -> listener.onWebSocketSessionCreated(this));
}
@Override
- public void close()
+ public void demand()
{
- coreSession.close(StatusCode.NORMAL, null, Callback.NOOP);
+ if (frameHandler.isAutoDemand())
+ throw new IllegalStateException("auto-demanding endpoint cannot explicitly demand");
+ coreSession.demand(1);
}
@Override
- public void close(CloseStatus closeStatus)
+ public void sendBinary(ByteBuffer buffer, Callback callback)
{
- coreSession.close(closeStatus.getCode(), closeStatus.getPhrase(), Callback.NOOP);
+ callback = Objects.requireNonNullElse(callback, Callback.NOOP);
+ coreSession.sendFrame(new Frame(OpCode.BINARY).setPayload(buffer),
+ org.eclipse.jetty.util.Callback.from(callback::succeed, callback::fail),
+ false);
}
@Override
- public void close(int statusCode, String reason)
+ public void sendPartialBinary(ByteBuffer buffer, boolean last, Callback callback)
{
- coreSession.close(statusCode, reason, Callback.NOOP);
- }
-
- @Override
- public void close(int statusCode, String reason, WriteCallback callback)
- {
- coreSession.close(statusCode, reason, Callback.from(callback::writeSuccess, callback::writeFailed));
- }
-
- @Override
- public WebSocketBehavior getBehavior()
- {
- switch (coreSession.getBehavior())
+ callback = Objects.requireNonNullElse(callback, Callback.NOOP);
+ Frame frame = switch (messageType)
{
- case CLIENT:
- return WebSocketBehavior.CLIENT;
- case SERVER:
- return WebSocketBehavior.SERVER;
- default:
- return null;
+ case OpCode.UNDEFINED ->
+ {
+ // new message
+ messageType = OpCode.BINARY;
+ yield new Frame(OpCode.BINARY);
+ }
+ case OpCode.BINARY -> new Frame(OpCode.CONTINUATION);
+ default ->
+ {
+ callback.fail(new ProtocolException("Attempt to send partial BINARY during " + OpCode.name(messageType)));
+ yield null;
+ }
+ };
+
+ if (frame != null)
+ {
+ frame.setPayload(buffer);
+ frame.setFin(last);
+
+ var cb = org.eclipse.jetty.util.Callback.from(callback::succeed, callback::fail);
+ coreSession.sendFrame(frame, cb, false);
+
+ if (last)
+ messageType = OpCode.UNDEFINED;
}
}
+ @Override
+ public void sendText(String text, Callback callback)
+ {
+ callback = Objects.requireNonNullElse(callback, Callback.NOOP);
+ var cb = org.eclipse.jetty.util.Callback.from(callback::succeed, callback::fail);
+ coreSession.sendFrame(new Frame(OpCode.TEXT).setPayload(text), cb, false);
+ }
+
+ @Override
+ public void sendPartialText(String text, boolean last, Callback callback)
+ {
+ Frame frame = switch (messageType)
+ {
+ case OpCode.UNDEFINED ->
+ {
+ // new message
+ messageType = OpCode.TEXT;
+ yield new Frame(OpCode.TEXT);
+ }
+ case OpCode.TEXT -> new Frame(OpCode.CONTINUATION);
+ default ->
+ {
+ callback.fail(new ProtocolException("Attempt to send partial TEXT during " + OpCode.name(messageType)));
+ yield null;
+ }
+ };
+
+ if (frame != null)
+ {
+ frame.setPayload(BufferUtil.toBuffer(text, UTF_8));
+ frame.setFin(last);
+
+ var cb = org.eclipse.jetty.util.Callback.from(callback::succeed, callback::fail);
+ coreSession.sendFrame(frame, cb, false);
+
+ if (last)
+ messageType = OpCode.UNDEFINED;
+ }
+ }
+
+ @Override
+ public void sendPing(ByteBuffer applicationData, Callback callback)
+ {
+ coreSession.sendFrame(new Frame(OpCode.PING).setPayload(applicationData),
+ org.eclipse.jetty.util.Callback.from(callback::succeed, callback::fail), false);
+ }
+
+ @Override
+ public void sendPong(ByteBuffer applicationData, Callback callback)
+ {
+ coreSession.sendFrame(new Frame(OpCode.PONG).setPayload(applicationData),
+ org.eclipse.jetty.util.Callback.from(callback::succeed, callback::fail), false);
+ }
+
+ @Override
+ public void close(int statusCode, String reason, Callback callback)
+ {
+ coreSession.close(statusCode, reason, org.eclipse.jetty.util.Callback.from(callback::succeed, callback::fail));
+ }
+
@Override
public Duration getIdleTimeout()
{
return coreSession.getIdleTimeout();
}
- @Override
- public int getInputBufferSize()
- {
- return coreSession.getInputBufferSize();
- }
-
- @Override
- public int getOutputBufferSize()
- {
- return coreSession.getOutputBufferSize();
- }
-
- @Override
- public long getMaxBinaryMessageSize()
- {
- return coreSession.getMaxBinaryMessageSize();
- }
-
- @Override
- public long getMaxTextMessageSize()
- {
- return coreSession.getMaxTextMessageSize();
- }
-
- @Override
- public long getMaxFrameSize()
- {
- return coreSession.getMaxFrameSize();
- }
-
- @Override
- public boolean isAutoFragment()
- {
- return coreSession.isAutoFragment();
- }
-
@Override
public void setIdleTimeout(Duration duration)
{
coreSession.setIdleTimeout(duration);
}
+ @Override
+ public int getInputBufferSize()
+ {
+ return coreSession.getInputBufferSize();
+ }
+
@Override
public void setInputBufferSize(int size)
{
coreSession.setInputBufferSize(size);
}
+ @Override
+ public int getOutputBufferSize()
+ {
+ return coreSession.getOutputBufferSize();
+ }
+
@Override
public void setOutputBufferSize(int size)
{
coreSession.setOutputBufferSize(size);
}
+ @Override
+ public long getMaxBinaryMessageSize()
+ {
+ return coreSession.getMaxBinaryMessageSize();
+ }
+
@Override
public void setMaxBinaryMessageSize(long size)
{
coreSession.setMaxBinaryMessageSize(size);
}
+ @Override
+ public long getMaxTextMessageSize()
+ {
+ return coreSession.getMaxTextMessageSize();
+ }
+
@Override
public void setMaxTextMessageSize(long size)
{
coreSession.setMaxTextMessageSize(size);
}
+ @Override
+ public long getMaxFrameSize()
+ {
+ return coreSession.getMaxFrameSize();
+ }
+
@Override
public void setMaxFrameSize(long maxFrameSize)
{
coreSession.setMaxFrameSize(maxFrameSize);
}
+ @Override
+ public boolean isAutoFragment()
+ {
+ return coreSession.isAutoFragment();
+ }
+
@Override
public void setAutoFragment(boolean autoFragment)
{
@@ -172,15 +245,21 @@ public class WebSocketSession implements Session, SuspendToken, Dumpable
}
@Override
- public String getProtocolVersion()
+ public int getMaxOutgoingFrames()
{
- return upgradeRequest.getProtocolVersion();
+ return coreSession.getMaxOutgoingFrames();
}
@Override
- public JettyWebSocketRemoteEndpoint getRemote()
+ public void setMaxOutgoingFrames(int maxOutgoingFrames)
{
- return remoteEndpoint;
+ coreSession.setMaxOutgoingFrames(maxOutgoingFrames);
+ }
+
+ @Override
+ public String getProtocolVersion()
+ {
+ return upgradeRequest.getProtocolVersion();
}
@Override
@@ -202,13 +281,13 @@ public class WebSocketSession implements Session, SuspendToken, Dumpable
}
@Override
- public SocketAddress getLocalAddress()
+ public SocketAddress getLocalSocketAddress()
{
return coreSession.getLocalAddress();
}
@Override
- public SocketAddress getRemoteAddress()
+ public SocketAddress getRemoteSocketAddress()
{
return coreSession.getRemoteAddress();
}
@@ -225,19 +304,6 @@ public class WebSocketSession implements Session, SuspendToken, Dumpable
return this.upgradeResponse;
}
- @Override
- public SuspendToken suspend()
- {
- frameHandler.suspend();
- return this;
- }
-
- @Override
- public void resume()
- {
- frameHandler.resume();
- }
-
public CoreSession getCoreSession()
{
return coreSession;
@@ -246,21 +312,20 @@ public class WebSocketSession implements Session, SuspendToken, Dumpable
@Override
public void dump(Appendable out, String indent) throws IOException
{
- Dumpable.dumpObjects(out, indent, this, upgradeRequest, coreSession, remoteEndpoint, frameHandler);
+ Dumpable.dumpObjects(out, indent, this, upgradeRequest, coreSession, frameHandler);
}
@Override
public String dumpSelf()
{
- return String.format("%s@%x[behavior=%s,idleTimeout=%dms]",
+ return String.format("%s@%x[idleTimeout=%dms]",
this.getClass().getSimpleName(), hashCode(),
- getPolicy().getBehavior(),
getIdleTimeout().toMillis());
}
@Override
public String toString()
{
- return String.format("WebSocketSession[%s,to=%s,%s,%s]", getBehavior(), getIdleTimeout(), coreSession, frameHandler);
+ return String.format("WebSocketSession[to=%s,%s,%s]", getIdleTimeout(), coreSession, frameHandler);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/ByteBufferMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/ByteBufferMessageSink.java
new file mode 100644
index 00000000000..4d9b6b3ef26
--- /dev/null
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/ByteBufferMessageSink.java
@@ -0,0 +1,40 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.common.internal;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.nio.ByteBuffer;
+
+import org.eclipse.jetty.websocket.api.Callback;
+import org.eclipse.jetty.websocket.core.CoreSession;
+import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
+
+public class ByteBufferMessageSink extends org.eclipse.jetty.websocket.core.messages.ByteBufferMessageSink
+{
+ public ByteBufferMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ {
+ super(session, methodHandle, autoDemand, false);
+
+ MethodType onMessageType = MethodType.methodType(Void.TYPE, ByteBuffer.class, Callback.class);
+ if (methodHandle.type() != onMessageType)
+ throw InvalidSignatureException.build(onMessageType, methodHandle.type());
+ }
+
+ @Override
+ protected void invoke(MethodHandle methodHandle, ByteBuffer byteBuffer, org.eclipse.jetty.util.Callback callback) throws Throwable
+ {
+ methodHandle.invoke(byteBuffer, Callback.from(callback::succeeded, callback::failed));
+ }
+}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/PartialByteBufferMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/PartialByteBufferMessageSink.java
new file mode 100644
index 00000000000..479e90cb779
--- /dev/null
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/PartialByteBufferMessageSink.java
@@ -0,0 +1,40 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.common.internal;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.nio.ByteBuffer;
+
+import org.eclipse.jetty.websocket.api.Callback;
+import org.eclipse.jetty.websocket.core.CoreSession;
+import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
+
+public class PartialByteBufferMessageSink extends org.eclipse.jetty.websocket.core.messages.PartialByteBufferMessageSink
+{
+ public PartialByteBufferMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ {
+ super(session, methodHandle, autoDemand);
+
+ MethodType onMessageType = MethodType.methodType(Void.TYPE, ByteBuffer.class, boolean.class, Callback.class);
+ if (methodHandle.type() != onMessageType)
+ throw InvalidSignatureException.build(onMessageType, methodHandle.type());
+ }
+
+ @Override
+ protected void invoke(MethodHandle methodHandle, ByteBuffer byteBuffer, boolean fin, org.eclipse.jetty.util.Callback callback) throws Throwable
+ {
+ methodHandle.invoke(byteBuffer, fin, Callback.from(callback::succeeded, callback::failed));
+ }
+}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/EndPoints.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/EndPoints.java
index 6cc0c3d91ce..91552bd21dc 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/EndPoints.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/EndPoints.java
@@ -13,24 +13,19 @@
package org.eclipse.jetty.websocket.common;
-import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Frame;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketFrameListener;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
-import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
-import org.eclipse.jetty.websocket.api.WebSocketPingPongListener;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.core.CloseStatus;
import org.eclipse.jetty.websocket.core.util.TextUtils;
@@ -44,14 +39,15 @@ public class EndPoints
{
}
- public static class ListenerBasicSocket implements WebSocketListener
+ public static class ListenerBasicSocket implements Session.Listener.AutoDemanding
{
public EventQueue events = new EventQueue();
@Override
- public void onWebSocketBinary(byte[] payload, int offset, int len)
+ public void onWebSocketBinary(ByteBuffer payload, Callback callback)
{
- events.add("onWebSocketBinary([%d], %d, %d)", payload.length, offset, len);
+ events.add("onWebSocketBinary([%d])", payload.remaining());
+ callback.succeed();
}
@Override
@@ -61,9 +57,9 @@ public class EndPoints
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
- events.add("onWebSocketConnect(%s)", session);
+ events.add("onWebSocketOpen(%s)", session);
}
@Override
@@ -79,7 +75,7 @@ public class EndPoints
}
}
- public static class ListenerFrameSocket implements WebSocketFrameListener
+ public static class ListenerFrameSocket implements Session.Listener.AutoDemanding
{
public EventQueue events = new EventQueue();
@@ -90,9 +86,9 @@ public class EndPoints
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
- events.add("onWebSocketConnect(%s)", session);
+ events.add("onWebSocketOpen(%s)", session);
}
@Override
@@ -102,13 +98,14 @@ public class EndPoints
}
@Override
- public void onWebSocketFrame(Frame frame)
+ public void onWebSocketFrame(Frame frame, Callback callback)
{
events.add("onWebSocketFrame(%s)", frame.toString());
+ callback.succeed();
}
}
- public static class ListenerPartialSocket implements WebSocketPartialListener
+ public static class ListenerPartialSocket implements Session.Listener.AutoDemanding
{
public EventQueue events = new EventQueue();
@@ -119,9 +116,9 @@ public class EndPoints
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
- events.add("onWebSocketConnect(%s)", session);
+ events.add("onWebSocketOpen(%s)", session);
}
@Override
@@ -137,13 +134,14 @@ public class EndPoints
}
@Override
- public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin)
+ public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin, Callback callback)
{
events.add("onWebSocketPartialBinary(%s, %b)", BufferUtil.toDetailString(payload), fin);
+ callback.succeed();
}
}
- public static class ListenerPingPongSocket implements WebSocketPingPongListener
+ public static class ListenerPingPongSocket implements Session.Listener.AutoDemanding
{
public EventQueue events = new EventQueue();
@@ -154,9 +152,9 @@ public class EndPoints
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
- events.add("onWebSocketConnect(%s)", session);
+ events.add("onWebSocketOpen(%s)", session);
}
@Override
@@ -184,52 +182,15 @@ public class EndPoints
@WebSocket
public static class BadDuplicateBinarySocket
{
- /**
- * First method
- *
- * @param payload the payload
- * @param offset the offset
- * @param len the len
- */
@OnWebSocketMessage
- public void binMe(byte[] payload, int offset, int len)
+ public void binMe(ByteBuffer payload, Callback callback)
{
- /* ignore */
+ callback.succeed();
}
- /**
- * Second method (also binary)
- *
- * @param stream the input stream
- */
@OnWebSocketMessage
public void streamMe(InputStream stream)
{
- /* ignore */
- }
- }
-
- @WebSocket
- public static class AnnotatedBinaryArraySocket
- {
- public EventQueue events = new EventQueue();
-
- @OnWebSocketMessage
- public void onBinary(byte[] payload, int offset, int length)
- {
- events.add("onBinary([%d],%d,%d)", payload.length, offset, length);
- }
-
- @OnWebSocketClose
- public void onClose(int statusCode, String reason)
- {
- events.add("onClose(%d, %s)", statusCode, TextUtils.quote(reason));
- }
-
- @OnWebSocketConnect
- public void onConnect(Session sess)
- {
- events.add("onConnect(%s)", sess);
}
}
@@ -251,10 +212,10 @@ public class EndPoints
events.add("onClose(%d, %s)", statusCode, TextUtils.quote(reason));
}
- @OnWebSocketConnect
- public void onConnect(Session sess)
+ @OnWebSocketOpen
+ public void onOpen(Session sess)
{
- events.add("onConnect(%s)", sess);
+ events.add("onOpen(%s)", sess);
}
}
@@ -269,10 +230,10 @@ public class EndPoints
events.add("onClose(%d, %s)", statusCode, TextUtils.quote(reason));
}
- @OnWebSocketConnect
- public void onConnect(Session sess)
+ @OnWebSocketOpen
+ public void onOpen(Session sess)
{
- events.add("onConnect(%s)", sess);
+ events.add("onOpen(%s)", sess);
}
@OnWebSocketError
@@ -299,10 +260,10 @@ public class EndPoints
events.add("onClose(%d, %s)", statusCode, TextUtils.quote(reason));
}
- @OnWebSocketConnect
- public void onConnect(Session sess)
+ @OnWebSocketOpen
+ public void onOpen(Session sess)
{
- events.add("onConnect(%s)", sess);
+ events.add("onOpen(%s)", sess);
}
@OnWebSocketMessage
@@ -379,18 +340,31 @@ public class EndPoints
}
}
+ @WebSocket(autoDemand = false)
+ public static class BadAutoDemandWithInputStream
+ {
+ @OnWebSocketMessage
+ public void onMessage(InputStream stream)
+ {
+ }
+ }
+
+ @WebSocket(autoDemand = false)
+ public static class BadAutoDemandWithReader
+ {
+ @OnWebSocketMessage
+ public void onMessage(Reader reader)
+ {
+ }
+ }
+
@WebSocket
public static class FrameSocket
{
- /**
- * A frame
- *
- * @param frame the frame
- */
@OnWebSocketFrame
- public void frameMe(Frame frame)
+ public void frameMe(Frame frame, Callback callback)
{
- /* ignore */
+ callback.succeed();
}
}
@@ -401,16 +375,9 @@ public class EndPoints
public static class MyEchoBinarySocket extends MyEchoSocket
{
@OnWebSocketMessage
- public void echoBin(byte[] buf, int offset, int length)
+ public void echoBin(ByteBuffer payload, Callback callback)
{
- try
- {
- getRemote().sendBytes(ByteBuffer.wrap(buf, offset, length));
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
+ getSession().sendBinary(payload, callback);
}
}
@@ -423,24 +390,16 @@ public class EndPoints
public static class MyEchoSocket
{
private Session session;
- private RemoteEndpoint remote;
- public RemoteEndpoint getRemote()
- {
- return remote;
- }
-
- @OnWebSocketClose
- public void onClose(int statusCode, String reason)
- {
- this.session = null;
- }
-
- @OnWebSocketConnect
- public void onConnect(Session session)
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
this.session = session;
- this.remote = session.getRemote();
+ }
+
+ public Session getSession()
+ {
+ return session;
}
@OnWebSocketMessage
@@ -453,14 +412,13 @@ public class EndPoints
return;
}
- try
- {
- remote.sendString(message);
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
+ session.sendText(message, Callback.NOOP);
+ }
+
+ @OnWebSocketClose
+ public void onClose(int statusCode, String reason)
+ {
+ this.session = null;
}
}
@@ -478,7 +436,7 @@ public class EndPoints
@OnWebSocketMessage
public void onText(Session session, String text)
{
- session.getRemote().sendString(text, null);
+ session.sendText(text, null);
}
}
@@ -498,8 +456,8 @@ public class EndPoints
*/
public static class NotASocket
{
- @OnWebSocketConnect
- public void onConnect(Session session)
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
/* do nothing */
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerTest.java
index e1801ca9a39..b4ccd135e94 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerTest.java
@@ -25,7 +25,6 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.api.WebSocketConnectionListener;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.core.Behavior;
@@ -91,7 +90,7 @@ public class JettyWebSocketFrameHandlerTest
return endpointFactory.newJettyFrameHandler(wsEndpoint);
}
- public static class ConnectionOnly implements WebSocketConnectionListener
+ public static class ConnectionOnly implements Session.Listener
{
public EventQueue events = new EventQueue();
@@ -102,9 +101,9 @@ public class JettyWebSocketFrameHandlerTest
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
- events.add("onWebSocketConnect(%s)", session);
+ events.add("onWebSocketOpen(%s)", session);
}
@Override
@@ -127,7 +126,7 @@ public class JettyWebSocketFrameHandlerTest
// Validate Events
socket.events.assertEvents(
- "onWebSocketConnect\\([^\\)]*\\)",
+ "onWebSocketOpen\\([^\\)]*\\)",
"onWebSocketClose\\([^\\)]*\\)");
}
@@ -222,7 +221,7 @@ public class JettyWebSocketFrameHandlerTest
// Validate Events
socket.events.assertEvents(
- "onWebSocketConnect\\([^\\)]*\\)",
+ "onWebSocketOpen\\([^\\)]*\\)",
"onWebSocketPartialText\\(\"Hello\", false\\)",
"onWebSocketPartialText\\(\" \", false\\)",
"onWebSocketPartialText\\(\"World\", true\\)",
@@ -252,9 +251,9 @@ public class JettyWebSocketFrameHandlerTest
// Validate Events
socket.events.assertEvents(
- "onWebSocketConnect\\([^\\)]*\\)",
+ "onWebSocketOpen\\([^\\)]*\\)",
"onWebSocketText\\(\"Hello World\"\\)",
- "onWebSocketBinary\\(\\[12\\], 0, 12\\)",
+ "onWebSocketBinary\\(\\[12\\]\\)",
"onWebSocketClose\\(NORMAL, \"Normal\"\\)"
);
}
@@ -274,7 +273,7 @@ public class JettyWebSocketFrameHandlerTest
// Validate Events
socket.events.assertEvents(
- "onWebSocketConnect\\([^\\)]*\\)",
+ "onWebSocketOpen\\([^\\)]*\\)",
"onWebSocketError\\(\\(RuntimeException\\) \"Nothing to see here\"\\)"
);
}
@@ -298,7 +297,7 @@ public class JettyWebSocketFrameHandlerTest
// Validate Events
socket.events.assertEvents(
- "onWebSocketConnect\\([^\\)]*\\)",
+ "onWebSocketOpen\\([^\\)]*\\)",
"onWebSocketFrame\\(.*TEXT@[0-9a-f]*.len=5,fin=false,.*\\)",
"onWebSocketFrame\\(.*CONTINUATION@[0-9a-f]*.len=1,fin=false,.*\\)",
"onWebSocketFrame\\(.*CONTINUATION@[0-9a-f]*.len=5,fin=true,.*\\)",
@@ -330,7 +329,7 @@ public class JettyWebSocketFrameHandlerTest
// Validate Events
socket.events.assertEvents(
- "onWebSocketConnect\\([^\\)]*\\)",
+ "onWebSocketOpen\\([^\\)]*\\)",
"onWebSocketPing\\(.*ByteBuffer.*You there.*\\)",
"onWebSocketPong\\(.*ByteBuffer.*You there.*\\)",
"onWebSocketClose\\(NORMAL, \"Normal\"\\)"
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/LocalEndpointMetadataTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/LocalEndpointMetadataTest.java
index 701c74c5b2f..98cf8a877a7 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/LocalEndpointMetadataTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/LocalEndpointMetadataTest.java
@@ -14,10 +14,10 @@
package org.eclipse.jetty.websocket.common;
import org.eclipse.jetty.websocket.api.exceptions.InvalidWebSocketException;
+import org.eclipse.jetty.websocket.common.internal.ByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.exception.DuplicateAnnotationException;
import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
-import org.eclipse.jetty.websocket.core.messages.ByteArrayMessageSink;
import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
import org.eclipse.jetty.websocket.core.messages.ReaderMessageSink;
import org.eclipse.jetty.websocket.core.messages.StringMessageSink;
@@ -104,29 +104,16 @@ public class LocalEndpointMetadataTest
assertThat(e.getMessage(), containsString("must not be static"));
}
- /**
- * Test Case for socket for binary array messages
- */
@Test
- public void testAnnotatedBinaryArraySocket() throws Exception
+ public void testAnnotatedBadAutoDemandWithInputStream()
{
- JettyWebSocketFrameHandlerMetadata metadata = createMetadata(EndPoints.AnnotatedBinaryArraySocket.class);
+ assertThrows(InvalidWebSocketException.class, () -> createMetadata(EndPoints.BadAutoDemandWithInputStream.class));
+ }
- String classId = EndPoints.AnnotatedBinaryArraySocket.class.getSimpleName();
-
- assertThat(classId + ".binaryHandle", metadata.getBinaryHandle(), EXISTS);
- assertThat(classId + ".binarySink", metadata.getBinarySink(), equalTo(ByteArrayMessageSink.class));
-
- assertThat(classId + ".textHandle", metadata.getTextHandle(), nullValue());
- assertThat(classId + ".textSink", metadata.getTextSink(), nullValue());
-
- assertThat(classId + ".openHandle", metadata.getOpenHandle(), EXISTS);
- assertThat(classId + ".closeHandle", metadata.getCloseHandle(), EXISTS);
- assertThat(classId + ".errorHandle", metadata.getErrorHandle(), nullValue());
-
- assertThat(classId + ".frameHandle", metadata.getFrameHandle(), nullValue());
- assertThat(classId + ".pingHandle", metadata.getPingHandle(), nullValue());
- assertThat(classId + ".pongHandle", metadata.getPongHandle(), nullValue());
+ @Test
+ public void testAnnotatedBadAutoDemandWithReader()
+ {
+ assertThrows(InvalidWebSocketException.class, () -> createMetadata(EndPoints.BadAutoDemandWithReader.class));
}
/**
@@ -165,7 +152,7 @@ public class LocalEndpointMetadataTest
String classId = EndPoints.MyEchoBinarySocket.class.getSimpleName();
assertThat(classId + ".binaryHandle", metadata.getBinaryHandle(), EXISTS);
- assertThat(classId + ".binarySink", metadata.getBinarySink(), equalTo(ByteArrayMessageSink.class));
+ assertThat(classId + ".binarySink", metadata.getBinarySink(), equalTo(ByteBufferMessageSink.class));
assertThat(classId + ".textHandle", metadata.getTextHandle(), EXISTS);
assertThat(classId + ".textSink", metadata.getTextSink(), equalTo(StringMessageSink.class));
@@ -337,7 +324,7 @@ public class LocalEndpointMetadataTest
String classId = EndPoints.ListenerBasicSocket.class.getSimpleName();
assertThat(classId + ".binaryHandle", metadata.getBinaryHandle(), EXISTS);
- assertThat(classId + ".binarySink", metadata.getBinarySink(), equalTo(ByteArrayMessageSink.class));
+ assertThat(classId + ".binarySink", metadata.getBinarySink(), equalTo(ByteBufferMessageSink.class));
assertThat(classId + ".textHandle", metadata.getTextHandle(), EXISTS);
assertThat(classId + ".textSink", metadata.getTextSink(), equalTo(StringMessageSink.class));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/MessageInputStreamTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/MessageInputStreamTest.java
index fe233f30aa3..025e1e8ee35 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/MessageInputStreamTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/MessageInputStreamTest.java
@@ -25,6 +25,7 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.MessageInputStream;
@@ -42,7 +43,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
// Append a single message (simple, short)
Frame frame = new Frame(OpCode.TEXT);
@@ -63,7 +64,7 @@ public class MessageInputStreamTest
@Test
public void testMultipleReadsIntoSingleByteArray() throws IOException
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
// Append a single message (simple, short)
Frame frame = new Frame(OpCode.TEXT);
@@ -95,7 +96,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
final AtomicBoolean hadError = new AtomicBoolean(false);
final CountDownLatch startLatch = new CountDownLatch(1);
@@ -140,7 +141,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
final AtomicBoolean hadError = new AtomicBoolean(false);
@@ -175,7 +176,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
final AtomicBoolean hadError = new AtomicBoolean(false);
@@ -221,7 +222,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
// Append parts of message
Frame msg1 = new Frame(OpCode.BINARY).setPayload("Hello ").setFin(false);
@@ -248,7 +249,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
// Append parts of message
Frame msg1 = new Frame(OpCode.BINARY).setPayload("Hello ").setFin(false);
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingMessageCapture.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingMessageCapture.java
index 8a15dcaa0da..c8970e284a1 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingMessageCapture.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingMessageCapture.java
@@ -22,12 +22,13 @@ import java.util.concurrent.LinkedBlockingDeque;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.toolchain.test.Hex;
-import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
+import org.eclipse.jetty.websocket.common.internal.ByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.CloseStatus;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
-import org.eclipse.jetty.websocket.core.messages.ByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.messages.StringMessageSink;
import org.slf4j.Logger;
@@ -45,7 +46,6 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
private final MethodHandle wholeTextHandle;
private final MethodHandle wholeBinaryHandle;
private MessageSink messageSink;
- private long maxMessageSize = 2 * 1024 * 1024;
public OutgoingMessageCapture()
{
@@ -55,7 +55,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
MethodHandle text = lookup.findVirtual(this.getClass(), "onWholeText", MethodType.methodType(Void.TYPE, String.class));
this.wholeTextHandle = text.bindTo(this);
- MethodHandle binary = lookup.findVirtual(this.getClass(), "onWholeBinary", MethodType.methodType(Void.TYPE, ByteBuffer.class));
+ MethodHandle binary = lookup.findVirtual(this.getClass(), "onWholeBinary", MethodType.methodType(Void.TYPE, ByteBuffer.class, Callback.class));
this.wholeBinaryHandle = binary.bindTo(this);
}
catch (NoSuchMethodException | IllegalAccessException e)
@@ -65,7 +65,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
}
@Override
- public void sendFrame(Frame frame, Callback callback, boolean batch)
+ public void sendFrame(Frame frame, org.eclipse.jetty.util.Callback callback, boolean batch)
{
switch (frame.getOpCode())
{
@@ -96,7 +96,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
String event = String.format("TEXT:fin=%b:len=%d", frame.isFin(), frame.getPayloadLength());
LOG.debug(event);
events.offer(event);
- messageSink = new StringMessageSink(this, wholeTextHandle);
+ messageSink = new StringMessageSink(this, wholeTextHandle, true);
break;
}
case OpCode.BINARY:
@@ -104,7 +104,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
String event = String.format("BINARY:fin=%b:len=%d", frame.isFin(), frame.getPayloadLength());
LOG.debug(event);
events.offer(event);
- messageSink = new ByteBufferMessageSink(this, wholeBinaryHandle);
+ messageSink = new ByteBufferMessageSink(this, wholeBinaryHandle, true);
break;
}
case OpCode.CONTINUATION:
@@ -119,7 +119,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
if (OpCode.isDataFrame(frame.getOpCode()))
{
Frame copy = Frame.copy(frame);
- messageSink.accept(copy, Callback.from(() -> {}, Throwable::printStackTrace));
+ messageSink.accept(copy, org.eclipse.jetty.util.Callback.from(() -> {}, Throwable::printStackTrace));
if (frame.isFin())
messageSink = null;
}
@@ -140,16 +140,10 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
}
@SuppressWarnings("unused")
- public void onWholeBinary(ByteBuffer buf)
+ public void onWholeBinary(ByteBuffer buf, Callback callback)
{
- ByteBuffer copy = null;
- if (buf != null)
- {
- copy = ByteBuffer.allocate(buf.remaining());
- copy.put(buf);
- copy.flip();
- }
- this.binaryMessages.offer(copy);
+ this.binaryMessages.offer(BufferUtil.copy(buf));
+ callback.succeed();
}
private String dataHint(ByteBuffer payload)
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/AdapterEchoSocket.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/AdapterEchoSocket.java
index 8ac340d22ef..f0fa7c3e0fe 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/AdapterEchoSocket.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/AdapterEchoSocket.java
@@ -13,30 +13,22 @@
package org.eclipse.jetty.websocket.common.endpoints.adapters;
-import java.io.IOException;
-
-import org.eclipse.jetty.websocket.api.WebSocketAdapter;
+import org.eclipse.jetty.websocket.api.Callback;
+import org.eclipse.jetty.websocket.api.Session;
/**
* Example EchoSocket using Adapter.
*/
-public class AdapterEchoSocket extends WebSocketAdapter
+public class AdapterEchoSocket extends Session.Listener.Abstract
{
@Override
public void onWebSocketText(String message)
{
- if (isConnected())
+ if (isOpen())
{
- try
- {
- System.out.printf("Echoing back message [%s]%n", message);
- // echo the message back
- getRemote().sendString(message);
- }
- catch (IOException e)
- {
- e.printStackTrace(System.err);
- }
+ System.out.printf("Echoing back message [%s]%n", message);
+ // echo the message back
+ getSession().sendText(message, Callback.NOOP);
}
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/AnnotatedEchoSocket.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/AnnotatedEchoSocket.java
index cf84ed378b8..037e060d04e 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/AnnotatedEchoSocket.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/AnnotatedEchoSocket.java
@@ -15,14 +15,21 @@ package org.eclipse.jetty.websocket.common.endpoints.adapters;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
/**
* Example EchoSocket using Annotations.
*/
-@WebSocket(maxTextMessageSize = 64 * 1024)
+@WebSocket
public class AnnotatedEchoSocket
{
+ @OnWebSocketOpen
+ public void onOpen(Session session)
+ {
+ session.setMaxTextMessageSize(64 * 1024);
+ }
+
@OnWebSocketMessage
public void onText(Session session, String message)
{
@@ -30,7 +37,7 @@ public class AnnotatedEchoSocket
{
System.out.printf("Echoing back message [%s]%n", message);
// echo the message back
- session.getRemote().sendString(message, null);
+ session.sendText(message, null);
}
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/ListenerEchoSocket.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/ListenerEchoSocket.java
index e7166867c27..42ae6e7112e 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/ListenerEchoSocket.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/endpoints/adapters/ListenerEchoSocket.java
@@ -13,20 +13,23 @@
package org.eclipse.jetty.websocket.common.endpoints.adapters;
+import java.nio.ByteBuffer;
+
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
/**
* Example EchoSocket using Listener.
*/
-public class ListenerEchoSocket implements WebSocketListener
+public class ListenerEchoSocket implements Session.Listener
{
private Session outbound;
@Override
- public void onWebSocketBinary(byte[] payload, int offset, int len)
+ public void onWebSocketBinary(ByteBuffer payload, Callback callback)
{
- /* only interested in text messages */
+ // only interested in text messages.
+ callback.succeed();
}
@Override
@@ -36,7 +39,7 @@ public class ListenerEchoSocket implements WebSocketListener
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
this.outbound = session;
}
@@ -54,7 +57,7 @@ public class ListenerEchoSocket implements WebSocketListener
{
System.out.printf("Echoing back message [%s]%n", message);
// echo the message back
- outbound.getRemote().sendString(message, null);
+ outbound.sendText(message, null);
}
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-server/src/main/java/org/eclipse/jetty/websocket/server/ServerWebSocketContainer.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-server/src/main/java/org/eclipse/jetty/websocket/server/ServerWebSocketContainer.java
index 71af709fa06..475f7910c9d 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-server/src/main/java/org/eclipse/jetty/websocket/server/ServerWebSocketContainer.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-server/src/main/java/org/eclipse/jetty/websocket/server/ServerWebSocketContainer.java
@@ -26,10 +26,9 @@ import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.thread.Invocable;
+import org.eclipse.jetty.websocket.api.Configurable;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketContainer;
-import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
import org.eclipse.jetty.websocket.common.SessionTracker;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
@@ -48,7 +47,7 @@ import org.slf4j.LoggerFactory;
* URI paths to WebSocket endpoints and configure WebSocket parameters such as idle timeouts,
* max WebSocket message sizes, etc.
*/
-public class ServerWebSocketContainer extends ContainerLifeCycle implements WebSocketContainer, WebSocketPolicy, Invocable
+public class ServerWebSocketContainer extends ContainerLifeCycle implements WebSocketContainer, Configurable, Invocable
{
private static final Logger LOG = LoggerFactory.getLogger(ServerWebSocketContainer.class);
@@ -113,12 +112,6 @@ public class ServerWebSocketContainer extends ContainerLifeCycle implements WebS
}
}
- @Override
- public WebSocketBehavior getBehavior()
- {
- return configuration.getBehavior();
- }
-
@Override
public Duration getIdleTimeout()
{
@@ -203,6 +196,18 @@ public class ServerWebSocketContainer extends ContainerLifeCycle implements WebS
configuration.setAutoFragment(autoFragment);
}
+ @Override
+ public int getMaxOutgoingFrames()
+ {
+ return configuration.getMaxOutgoingFrames();
+ }
+
+ @Override
+ public void setMaxOutgoingFrames(int maxOutgoingFrames)
+ {
+ configuration.setMaxOutgoingFrames(maxOutgoingFrames);
+ }
+
/**
* Maps the given {@code pathSpec} to the creator of WebSocket endpoints.
* The {@code pathSpec} format is that supported by
@@ -296,12 +301,7 @@ public class ServerWebSocketContainer extends ContainerLifeCycle implements WebS
this.invocationType = invocationType;
}
- private static class Configuration extends org.eclipse.jetty.websocket.core.Configuration.ConfigurationCustomizer implements WebSocketPolicy
+ private static class Configuration extends org.eclipse.jetty.websocket.core.Configuration.ConfigurationCustomizer implements Configurable
{
- @Override
- public WebSocketBehavior getBehavior()
- {
- return WebSocketBehavior.SERVER;
- }
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/AnnoMaxMessageEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/AnnoMaxMessageEndpoint.java
index 7b3cf15a9af..2ddeb1ca344 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/AnnoMaxMessageEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/AnnoMaxMessageEndpoint.java
@@ -15,17 +15,24 @@ package org.eclipse.jetty.websocket.tests;
import java.io.IOException;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
-@SuppressWarnings("unused")
-@WebSocket(maxTextMessageSize = 100 * 1024)
+@WebSocket
public class AnnoMaxMessageEndpoint
{
+ @OnWebSocketOpen
+ public void onOpen(Session session)
+ {
+ session.setMaxTextMessageSize(100 * 1024);
+ }
+
@OnWebSocketMessage
public void onMessage(Session session, String msg) throws IOException
{
- session.getRemote().sendString(msg);
+ session.sendText(msg, Callback.NOOP);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/AnnotatedPartialListenerTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/AnnotatedPartialListenerTest.java
index 94305bfe218..eb12483e66d 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/AnnotatedPartialListenerTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/AnnotatedPartialListenerTest.java
@@ -24,9 +24,8 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
-import org.eclipse.jetty.websocket.api.WriteCallback;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.exceptions.InvalidWebSocketException;
@@ -42,26 +41,26 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
public class AnnotatedPartialListenerTest
{
- public static class PartialEchoSocket implements WebSocketPartialListener
+ public static class PartialEchoSocket implements Session.Listener.AutoDemanding
{
private Session session;
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
this.session = session;
}
@Override
- public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin)
+ public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin, Callback callback)
{
- session.getRemote().sendPartialBytes(payload, fin, WriteCallback.NOOP);
+ session.sendPartialBinary(payload, fin, callback);
}
@Override
public void onWebSocketPartialText(String payload, boolean fin)
{
- session.getRemote().sendPartialString(payload, fin, WriteCallback.NOOP);
+ session.sendPartialText(payload, fin, Callback.NOOP);
}
}
@@ -98,12 +97,13 @@ public class AnnotatedPartialListenerTest
}
@OnWebSocketMessage
- public void onMessage(ByteBuffer buffer, boolean last)
+ public void onMessage(ByteBuffer buffer, boolean last, Callback callback)
{
MessageSegment messageSegment = new MessageSegment();
messageSegment.buffer = BufferUtil.copy(buffer);
messageSegment.last = last;
messages.add(messageSegment);
+ callback.succeed();
}
}
@@ -111,12 +111,12 @@ public class AnnotatedPartialListenerTest
public static class InvalidDoubleBinaryListener
{
@OnWebSocketMessage
- public void onMessage(ByteBuffer bytes, boolean last)
+ public void onMessage(ByteBuffer bytes, boolean last, Callback callback)
{
}
@OnWebSocketMessage
- public void onMessage(ByteBuffer bytes)
+ public void onMessage(ByteBuffer bytes, Callback callback)
{
}
}
@@ -175,9 +175,10 @@ public class AnnotatedPartialListenerTest
PartialStringListener endpoint = new PartialStringListener();
try (Session session = client.connect(endpoint, serverUri).get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendPartialString("hell", false);
- session.getRemote().sendPartialString("o w", false);
- session.getRemote().sendPartialString("orld", true);
+ Callback.Completable.with(c -> session.sendPartialText("hell", false, c))
+ .compose(c -> session.sendPartialText("o w", false, c))
+ .compose(c -> session.sendPartialText("orld", true, c))
+ .get();
}
PartialStringListener.MessageSegment segment;
@@ -201,9 +202,10 @@ public class AnnotatedPartialListenerTest
PartialByteBufferListener endpoint = new PartialByteBufferListener();
try (Session session = client.connect(endpoint, serverUri).get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendPartialBytes(BufferUtil.toBuffer("hell"), false);
- session.getRemote().sendPartialBytes(BufferUtil.toBuffer("o w"), false);
- session.getRemote().sendPartialBytes(BufferUtil.toBuffer("orld"), true);
+ Callback.Completable.with(c -> session.sendPartialBinary(BufferUtil.toBuffer("hell"), false, c))
+ .compose(c -> session.sendPartialBinary(BufferUtil.toBuffer("o w"), false, c))
+ .compose(c -> session.sendPartialBinary(BufferUtil.toBuffer("orld"), true, c))
+ .get();
}
PartialByteBufferListener.MessageSegment segment;
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/CloseTrackingEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/CloseTrackingEndpoint.java
index fe50e849776..ebc6453f613 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/CloseTrackingEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/CloseTrackingEndpoint.java
@@ -21,8 +21,9 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.core.WebSocketConnection;
import org.eclipse.jetty.websocket.core.WebSocketCoreSession;
@@ -35,7 +36,7 @@ import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
-public class CloseTrackingEndpoint extends WebSocketAdapter
+public class CloseTrackingEndpoint extends Session.Listener.AbstractAutoDemanding
{
private static final Logger LOG = LoggerFactory.getLogger(CloseTrackingEndpoint.class);
@@ -43,7 +44,7 @@ public class CloseTrackingEndpoint extends WebSocketAdapter
public String closeReason = null;
public CountDownLatch closeLatch = new CountDownLatch(1);
public AtomicInteger closeCount = new AtomicInteger(0);
- public CountDownLatch openLatch = new CountDownLatch(1);
+ public CountDownLatch connectLatch = new CountDownLatch(1);
public CountDownLatch errorLatch = new CountDownLatch(1);
public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>();
@@ -89,11 +90,11 @@ public class CloseTrackingEndpoint extends WebSocketAdapter
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
- LOG.debug("onWebSocketConnect({})", session);
- super.onWebSocketConnect(session);
- openLatch.countDown();
+ super.onWebSocketOpen(session);
+ LOG.debug("onWebSocketOpen({})", session);
+ connectLatch.countDown();
}
@Override
@@ -112,10 +113,11 @@ public class CloseTrackingEndpoint extends WebSocketAdapter
}
@Override
- public void onWebSocketBinary(byte[] payload, int offset, int len)
+ public void onWebSocketBinary(ByteBuffer payload, Callback callback)
{
- LOG.debug("onWebSocketBinary({},{},{})", payload, offset, len);
- binaryMessageQueue.offer(ByteBuffer.wrap(payload, offset, len));
+ LOG.debug("onWebSocketBinary({})", payload.remaining());
+ binaryMessageQueue.offer(BufferUtil.copy(payload));
+ callback.succeed();
}
public EndPoint getEndPoint()
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConcurrentConnectTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConcurrentConnectTest.java
index 61f0166487c..7852522711d 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConcurrentConnectTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConcurrentConnectTest.java
@@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
@@ -104,9 +105,9 @@ public class ConcurrentConnectTest
for (EventSocket l : listeners)
{
- l.session.getRemote().sendString("ping");
+ l.session.sendText("ping", Callback.NOOP);
assertThat(l.textMessages.poll(5, TimeUnit.SECONDS), is("ping"));
- l.session.close(StatusCode.NORMAL, "close from client");
+ l.session.close(StatusCode.NORMAL, "close from client", Callback.NOOP);
}
for (EventSocket l : listeners)
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConnectMessageEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConnectMessageEndpoint.java
index f741f464c5d..fefd2287326 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConnectMessageEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConnectMessageEndpoint.java
@@ -13,19 +13,18 @@
package org.eclipse.jetty.websocket.tests;
-import java.io.IOException;
-
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@SuppressWarnings("unused")
@WebSocket
public class ConnectMessageEndpoint
{
- @OnWebSocketConnect
- public void onConnect(Session session) throws IOException
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
- session.getRemote().sendString("Greeting from onConnect");
+ session.sendText("Greeting from onOpen", Callback.NOOP);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConnectionHeaderTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConnectionHeaderTest.java
index fd93c0546ea..0c90af8522a 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConnectionHeaderTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ConnectionHeaderTest.java
@@ -22,6 +22,7 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.JettyUpgradeListener;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -92,7 +93,7 @@ public class ConnectionHeaderTest
{
// Generate text frame
String msg = "this is an echo ... cho ... ho ... o";
- session.getRemote().sendString(msg);
+ session.sendText(msg, Callback.NOOP);
// Read frame (hopefully text frame)
String response = clientEndpoint.textMessages.poll(5, TimeUnit.SECONDS);
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/DemandWithBlockingStreamsTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/DemandWithBlockingStreamsTest.java
new file mode 100644
index 00000000000..7173bcc5452
--- /dev/null
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/DemandWithBlockingStreamsTest.java
@@ -0,0 +1,153 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.tests;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.util.component.LifeCycle;
+import org.eclipse.jetty.websocket.api.Callback;
+import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.api.StatusCode;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
+import org.eclipse.jetty.websocket.api.annotations.WebSocket;
+import org.eclipse.jetty.websocket.client.WebSocketClient;
+import org.eclipse.jetty.websocket.server.WebSocketUpgradeHandler;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class DemandWithBlockingStreamsTest
+{
+ private final Server server = new Server();
+ private final ServerConnector connector = new ServerConnector(server, 1, 1);
+ private final WebSocketClient client = new WebSocketClient();
+
+ private void start(Consumer configurer) throws Exception
+ {
+ server.addConnector(connector);
+
+ ContextHandler context = new ContextHandler("/");
+
+ WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server, context);
+ context.setHandler(wsHandler);
+ configurer.accept(wsHandler);
+
+ server.setHandler(context);
+ server.start();
+
+ client.start();
+ }
+
+ @AfterEach
+ public void dispose()
+ {
+ LifeCycle.stop(client);
+ LifeCycle.stop(server);
+ }
+
+ @Test
+ public void testBinaryStreamExplicitDemandThrows() throws Exception
+ {
+ StreamEndPoint serverEndPoint = new StreamEndPoint();
+ start(wsHandler -> wsHandler.configure(container ->
+ container.addMapping("/*", (rq, rs, cb) -> serverEndPoint)));
+
+ URI uri = new URI("ws://localhost:" + connector.getLocalPort() + "/");
+ EventSocket clientEndPoint = new EventSocket();
+ client.connect(clientEndPoint, uri).get(5, TimeUnit.SECONDS);
+
+ clientEndPoint.session.sendBinary(ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8)), Callback.NOOP);
+
+ // The server-side tried to demand(), should get an error.
+ assertTrue(serverEndPoint.errorLatch.await(5, TimeUnit.SECONDS));
+ assertTrue(serverEndPoint.closeLatch.await(5, TimeUnit.SECONDS));
+ assertTrue(clientEndPoint.closeLatch.await(5, TimeUnit.SECONDS));
+ assertEquals(StatusCode.SERVER_ERROR, clientEndPoint.closeCode);
+ }
+
+ @Test
+ public void testTextStreamExplicitDemandThrows() throws Exception
+ {
+ StreamEndPoint serverEndPoint = new StreamEndPoint();
+ start(wsHandler -> wsHandler.configure(container ->
+ container.addMapping("/*", (rq, rs, cb) -> serverEndPoint)));
+
+ URI uri = new URI("ws://localhost:" + connector.getLocalPort() + "/");
+ EventSocket clientEndPoint = new EventSocket();
+ client.connect(clientEndPoint, uri).get(5, TimeUnit.SECONDS);
+
+ clientEndPoint.session.sendText("hello", Callback.NOOP);
+
+ // The server-side tried to demand(), should get an error.
+ assertTrue(serverEndPoint.errorLatch.await(5, TimeUnit.SECONDS));
+ assertTrue(serverEndPoint.closeLatch.await(5, TimeUnit.SECONDS));
+ assertTrue(clientEndPoint.closeLatch.await(5, TimeUnit.SECONDS));
+ assertEquals(StatusCode.SERVER_ERROR, clientEndPoint.closeCode);
+ }
+
+ @WebSocket
+ public static class StreamEndPoint
+ {
+ private final CountDownLatch errorLatch = new CountDownLatch(1);
+ private final CountDownLatch closeLatch = new CountDownLatch(1);
+ private Session session;
+
+ @OnWebSocketOpen
+ public void onOpen(Session session)
+ {
+ this.session = session;
+ }
+
+ @OnWebSocketMessage
+ public void onBinary(InputStream stream)
+ {
+ // Throws because this endpoint is auto-demanding.
+ session.demand();
+ }
+
+ @OnWebSocketMessage
+ public void onText(Reader reader)
+ {
+ // Throws because this endpoint is auto-demanding.
+ session.demand();
+ }
+
+ @OnWebSocketError
+ public void onError(Throwable cause)
+ {
+ errorLatch.countDown();
+ }
+
+ @OnWebSocketClose
+ public void onClose(int status, String reason)
+ {
+ closeLatch.countDown();
+ }
+ }
+}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/EchoSocket.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/EchoSocket.java
index 235c606b122..e0fef023d45 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/EchoSocket.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/EchoSocket.java
@@ -16,9 +16,9 @@ package org.eclipse.jetty.websocket.tests;
import java.io.IOException;
import java.nio.ByteBuffer;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
-@SuppressWarnings("unused")
@WebSocket
public class EchoSocket extends EventSocket
{
@@ -26,13 +26,13 @@ public class EchoSocket extends EventSocket
public void onMessage(String message) throws IOException
{
super.onMessage(message);
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
}
@Override
- public void onMessage(byte[] buf, int offset, int len) throws IOException
+ public void onMessage(ByteBuffer message, Callback callback) throws IOException
{
- super.onMessage(buf, offset, len);
- session.getRemote().sendBytes(ByteBuffer.wrap(buf, offset, len));
+ super.onMessage(message, Callback.NOOP);
+ session.sendBinary(message, callback);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ErrorCloseTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ErrorCloseTest.java
index 0df60aed83a..b817e395b3a 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ErrorCloseTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ErrorCloseTest.java
@@ -25,6 +25,7 @@ import org.eclipse.jetty.logging.StacklessLogging;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@@ -152,7 +153,7 @@ public class ErrorCloseTest
serverSocket.methodsToThrow.add("onMessage");
EventSocket clientSocket = new EventSocket();
client.connect(clientSocket, serverUri).get(5, TimeUnit.SECONDS);
- clientSocket.session.getRemote().sendString("trigger onMessage error");
+ clientSocket.session.sendText("trigger onMessage error", Callback.NOOP);
assertTrue(serverSocket.closeLatch.await(5, TimeUnit.SECONDS));
assertTrue(clientSocket.closeLatch.await(5, TimeUnit.SECONDS));
@@ -194,7 +195,7 @@ public class ErrorCloseTest
try (StacklessLogging ignored = new StacklessLogging(WebSocketSession.class))
{
- clientSocket.session.getRemote().sendString("trigger onMessage error");
+ clientSocket.session.sendText("trigger onMessage error", Callback.NOOP);
assertTrue(serverSocket.closeLatch.await(5, TimeUnit.SECONDS));
assertTrue(clientSocket.closeLatch.await(5, TimeUnit.SECONDS));
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/EventSocket.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/EventSocket.java
index 44c6db9d512..81f4d8b6743 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/EventSocket.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/EventSocket.java
@@ -19,12 +19,14 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import org.eclipse.jetty.util.BlockingArrayQueue;
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +37,6 @@ public class EventSocket
private static final Logger LOG = LoggerFactory.getLogger(EventSocket.class);
public Session session;
- private String behavior;
public BlockingQueue textMessages = new BlockingArrayQueue<>();
public BlockingQueue binaryMessages = new BlockingArrayQueue<>();
@@ -47,11 +48,10 @@ public class EventSocket
public CountDownLatch errorLatch = new CountDownLatch(1);
public CountDownLatch closeLatch = new CountDownLatch(1);
- @OnWebSocketConnect
+ @OnWebSocketOpen
public void onOpen(Session session)
{
this.session = session;
- behavior = session.getPolicy().getBehavior().name();
if (LOG.isDebugEnabled())
LOG.debug("{} onOpen(): {}", this, session);
openLatch.countDown();
@@ -66,12 +66,12 @@ public class EventSocket
}
@OnWebSocketMessage
- public void onMessage(byte[] buf, int offset, int len) throws IOException
+ public void onMessage(ByteBuffer message, Callback callback) throws IOException
{
- ByteBuffer message = ByteBuffer.wrap(buf, offset, len);
if (LOG.isDebugEnabled())
LOG.debug("{} onMessage(): {}", this, message);
- binaryMessages.offer(message);
+ binaryMessages.offer(BufferUtil.copy(message));
+ callback.succeed();
}
@OnWebSocketClose
@@ -96,6 +96,6 @@ public class EventSocket
@Override
public String toString()
{
- return String.format("[%s@%s]", behavior, Integer.toHexString(hashCode()));
+ return String.format("[%s@%x]", getClass().getSimpleName(), hashCode());
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SuspendResumeTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ExplicitDemandTest.java
similarity index 51%
rename from jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SuspendResumeTest.java
rename to jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ExplicitDemandTest.java
index e5d37107b78..263ecd5840d 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SuspendResumeTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ExplicitDemandTest.java
@@ -21,8 +21,8 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.SuspendToken;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeHandler;
@@ -33,22 +33,26 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-public class SuspendResumeTest
+public class ExplicitDemandTest
{
- @WebSocket
+ @WebSocket(autoDemand = false)
public static class SuspendSocket extends EventSocket
{
- volatile SuspendToken suspendToken = null;
+ @Override
+ public void onOpen(Session session)
+ {
+ super.onOpen(session);
+ session.demand();
+ }
@Override
public void onMessage(String message) throws IOException
{
- if ("suspend".equals(message))
- suspendToken = session.suspend();
super.onMessage(message);
+ if (!"suspend".equals(message))
+ session.demand();
}
}
@@ -84,25 +88,25 @@ public class SuspendResumeTest
}
@Test
- public void testSuspendWhenProcessingFrame() throws Exception
+ public void testNoDemandWhenProcessingFrame() throws Exception
{
URI uri = new URI("ws://localhost:" + connector.getLocalPort() + "/suspend");
EventSocket clientSocket = new EventSocket();
Future connect = client.connect(clientSocket, uri);
connect.get(5, TimeUnit.SECONDS);
- clientSocket.session.getRemote().sendString("suspend");
- clientSocket.session.getRemote().sendString("suspend");
- clientSocket.session.getRemote().sendString("hello world");
+ clientSocket.session.sendText("suspend", Callback.NOOP);
+ clientSocket.session.sendText("suspend", Callback.NOOP);
+ clientSocket.session.sendText("hello world", Callback.NOOP);
assertThat(serverSocket.textMessages.poll(5, TimeUnit.SECONDS), is("suspend"));
assertNull(serverSocket.textMessages.poll(1, TimeUnit.SECONDS));
- serverSocket.suspendToken.resume();
+ serverSocket.session.demand();
assertThat(serverSocket.textMessages.poll(5, TimeUnit.SECONDS), is("suspend"));
assertNull(serverSocket.textMessages.poll(1, TimeUnit.SECONDS));
- serverSocket.suspendToken.resume();
+ serverSocket.session.demand();
assertThat(serverSocket.textMessages.poll(5, TimeUnit.SECONDS), is("hello world"));
assertNull(serverSocket.textMessages.poll(1, TimeUnit.SECONDS));
@@ -115,68 +119,4 @@ public class SuspendResumeTest
assertNull(clientSocket.error);
assertNull(serverSocket.error);
}
-
- @Test
- public void testExternalSuspend() throws Exception
- {
- URI uri = new URI("ws://localhost:" + connector.getLocalPort() + "/suspend");
- EventSocket clientSocket = new EventSocket();
- Future connect = client.connect(clientSocket, uri);
- connect.get(5, TimeUnit.SECONDS);
-
- // verify connection by sending a message from server to client
- assertTrue(serverSocket.openLatch.await(5, TimeUnit.SECONDS));
- serverSocket.session.getRemote().sendString("verification");
- assertThat(clientSocket.textMessages.poll(5, TimeUnit.SECONDS), is("verification"));
-
- // suspend the client so that no read events occur
- SuspendToken suspendToken = clientSocket.session.suspend();
-
- // verify client can still send messages
- clientSocket.session.getRemote().sendString("message-from-client");
- assertThat(serverSocket.textMessages.poll(5, TimeUnit.SECONDS), is("message-from-client"));
-
- // the message is not received as it is suspended
- serverSocket.session.getRemote().sendString("message-from-server");
- assertNull(clientSocket.textMessages.poll(2, TimeUnit.SECONDS));
-
- // client should receive message after it resumes
- suspendToken.resume();
- assertThat(clientSocket.textMessages.poll(5, TimeUnit.SECONDS), is("message-from-server"));
-
- // make sure both sides are closed
- clientSocket.session.close();
- assertTrue(clientSocket.closeLatch.await(5, TimeUnit.SECONDS));
- assertTrue(serverSocket.closeLatch.await(5, TimeUnit.SECONDS));
-
- // check no errors occurred
- assertNull(clientSocket.error);
- assertNull(serverSocket.error);
- }
-
- @Test
- public void testSuspendAfterClose() throws Exception
- {
- URI uri = new URI("ws://localhost:" + connector.getLocalPort() + "/suspend");
- EventSocket clientSocket = new EventSocket();
- Future connect = client.connect(clientSocket, uri);
- connect.get(5, TimeUnit.SECONDS);
-
- // verify connection by sending a message from server to client
- assertTrue(serverSocket.openLatch.await(5, TimeUnit.SECONDS));
- serverSocket.session.getRemote().sendString("verification");
- assertThat(clientSocket.textMessages.poll(5, TimeUnit.SECONDS), is("verification"));
-
- // make sure both sides are closed
- clientSocket.session.close();
- assertTrue(clientSocket.closeLatch.await(5, TimeUnit.SECONDS));
- assertTrue(serverSocket.closeLatch.await(5, TimeUnit.SECONDS));
-
- // check no errors occurred
- assertNull(clientSocket.error);
- assertNull(serverSocket.error);
-
- // suspend after closed throws ISE
- assertThrows(IllegalStateException.class, () -> clientSocket.session.suspend());
- }
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/GetAuthHeaderEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/GetAuthHeaderEndpoint.java
index fdf15fc562d..9c8a4f1677d 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/GetAuthHeaderEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/GetAuthHeaderEndpoint.java
@@ -13,21 +13,20 @@
package org.eclipse.jetty.websocket.tests;
-import java.io.IOException;
-
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@SuppressWarnings("unused")
@WebSocket
public class GetAuthHeaderEndpoint
{
- @OnWebSocketConnect
- public void onConnect(Session session) throws IOException
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
String authHeaderName = "Authorization";
String authHeaderValue = session.getUpgradeRequest().getHeader(authHeaderName);
- session.getRemote().sendString("Header[" + authHeaderName + "]=" + authHeaderValue);
+ session.sendText("Header[" + authHeaderName + "]=" + authHeaderValue, Callback.NOOP);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyOnCloseTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyOnCloseTest.java
index ac6d18fa926..6d2a2d04760 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyOnCloseTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyOnCloseTest.java
@@ -21,6 +21,7 @@ import java.util.function.Consumer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@@ -123,7 +124,7 @@ public class JettyOnCloseTest
client.connect(clientEndpoint, uri).get(5, TimeUnit.SECONDS);
assertTrue(serverEndpoint.openLatch.await(5, TimeUnit.SECONDS));
- serverEndpoint.setOnClose((session) -> session.close(StatusCode.SERVICE_RESTART, "custom close reason"));
+ serverEndpoint.setOnClose((session) -> session.close(StatusCode.SERVICE_RESTART, "custom close reason", Callback.NOOP));
clientEndpoint.session.close();
assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
@@ -139,9 +140,9 @@ public class JettyOnCloseTest
client.connect(clientEndpoint, uri).get(5, TimeUnit.SECONDS);
assertTrue(serverEndpoint.openLatch.await(5, TimeUnit.SECONDS));
- serverEndpoint.setOnClose(Session::close);
+ serverEndpoint.setOnClose(session -> session.close());
- serverEndpoint.session.close(StatusCode.NORMAL, "first close");
+ serverEndpoint.session.close(StatusCode.NORMAL, "first close", Callback.NOOP);
assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(clientEndpoint.closeCode, is(StatusCode.NORMAL));
assertThat(clientEndpoint.closeReason, is("first close"));
@@ -157,11 +158,11 @@ public class JettyOnCloseTest
assertTrue(serverEndpoint.openLatch.await(5, TimeUnit.SECONDS));
serverEndpoint.setOnClose((session) ->
{
- session.close(StatusCode.SERVER_ERROR, "abnormal close 2");
+ session.close(StatusCode.SERVER_ERROR, "abnormal close 2", Callback.NOOP);
clientEndpoint.unBlockClose();
});
- serverEndpoint.session.close(StatusCode.PROTOCOL, "abnormal close 1");
+ serverEndpoint.session.close(StatusCode.PROTOCOL, "abnormal close 1", Callback.NOOP);
assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(clientEndpoint.closeCode, is(StatusCode.PROTOCOL));
assertThat(clientEndpoint.closeReason, is("abnormal close 1"));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyWebSocketExtensionConfigTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyWebSocketExtensionConfigTest.java
index 933765e4115..71e8dfd80e9 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyWebSocketExtensionConfigTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyWebSocketExtensionConfigTest.java
@@ -25,6 +25,7 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.ExtensionConfig;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
@@ -120,7 +121,7 @@ public class JettyWebSocketExtensionConfigTest
CompletableFuture connect = client.connect(socket, uri, request, listener);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello world");
+ session.sendText("hello world", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
assertTrue(correctResponseExtensions.await(5, TimeUnit.SECONDS));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/LargeDeflateTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/LargeDeflateTest.java
index 235f729386b..e42d19ee679 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/LargeDeflateTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/LargeDeflateTest.java
@@ -23,6 +23,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
@@ -85,8 +86,8 @@ public class LargeDeflateTest
EventSocket clientSocket = new EventSocket();
Session session = _client.connect(clientSocket, URI.create("ws://localhost:" + _connector.getLocalPort() + "/ws"), upgradeRequest).get();
ByteBuffer sentMessage = largePayloads();
- session.getRemote().sendBytes(sentMessage);
- session.close(StatusCode.NORMAL, "close from test");
+ session.sendBinary(sentMessage, Callback.NOOP);
+ session.close(StatusCode.NORMAL, "close from test", Callback.NOOP);
assertTrue(_serverSocket.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(_serverSocket.closeCode, is(StatusCode.NORMAL));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/MaxOutgoingFramesTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/MaxOutgoingFramesTest.java
index 0d280eecf36..0e55a17a793 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/MaxOutgoingFramesTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/MaxOutgoingFramesTest.java
@@ -22,16 +22,14 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.util.Callback;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
-import org.eclipse.jetty.websocket.api.WriteCallback;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.core.AbstractExtension;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeHandler;
-import org.eclipse.jetty.websocket.tests.util.FutureWriteCallback;
+import org.eclipse.jetty.websocket.tests.util.FutureCallback;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -95,7 +93,7 @@ public class MaxOutgoingFramesTest
}
@Override
- public void sendFrame(Frame frame, Callback callback, boolean batch)
+ public void sendFrame(Frame frame, org.eclipse.jetty.util.Callback callback, boolean batch)
{
try
{
@@ -110,7 +108,7 @@ public class MaxOutgoingFramesTest
}
}
- public static class CountingCallback implements WriteCallback
+ public static class CountingCallback implements Callback
{
private final CountDownLatch successes;
@@ -120,13 +118,13 @@ public class MaxOutgoingFramesTest
}
@Override
- public void writeSuccess()
+ public void succeed()
{
successes.countDown();
}
@Override
- public void writeFailed(Throwable t)
+ public void fail(Throwable t)
{
t.printStackTrace();
}
@@ -147,22 +145,21 @@ public class MaxOutgoingFramesTest
assertTrue(socket.openLatch.await(5, TimeUnit.SECONDS));
int numFrames = 30;
- RemoteEndpoint remote = socket.session.getRemote();
- remote.setMaxOutgoingFrames(numFrames);
+ socket.session.setMaxOutgoingFrames(numFrames);
// Verify that we can send up to numFrames without any problem.
// First send will block in the Extension so it needs to be done in new thread, others frames will be queued.
CountingCallback countingCallback = new CountingCallback(numFrames);
- new Thread(() -> remote.sendString("0", countingCallback)).start();
+ new Thread(() -> socket.session.sendText("0", countingCallback)).start();
assertTrue(firstFrameBlocked.await(5, TimeUnit.SECONDS));
for (int i = 1; i < numFrames; i++)
{
- remote.sendString(Integer.toString(i), countingCallback);
+ socket.session.sendText(Integer.toString(i), countingCallback);
}
// Sending any more frames will result in WritePendingException.
- FutureWriteCallback callback = new FutureWriteCallback();
- remote.sendString("fail", callback);
+ FutureCallback callback = new FutureCallback();
+ socket.session.sendText("fail", callback);
ExecutionException executionException = assertThrows(ExecutionException.class, () -> callback.get(5, TimeUnit.SECONDS));
assertThat(executionException.getCause(), instanceOf(WritePendingException.class));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ParamsEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ParamsEndpoint.java
index 090ca481882..11415b63462 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ParamsEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/ParamsEndpoint.java
@@ -13,21 +13,21 @@
package org.eclipse.jetty.websocket.tests;
-import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@SuppressWarnings("unused")
@WebSocket
public class ParamsEndpoint
{
- @OnWebSocketConnect
- public void onConnect(Session session) throws IOException
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
Map> params = session.getUpgradeRequest().getParameterMap();
StringBuilder msg = new StringBuilder();
@@ -39,6 +39,6 @@ public class ParamsEndpoint
msg.append("\n");
}
- session.getRemote().sendString(msg.toString());
+ session.sendText(msg.toString(), Callback.NOOP);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SimpleEchoTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SimpleEchoTest.java
index 4030ae37ca1..b203f14e0c1 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SimpleEchoTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SimpleEchoTest.java
@@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -82,7 +83,7 @@ public class SimpleEchoTest
session.setIdleTimeout(Duration.ofSeconds(timeout));
String message = "hello world 1234";
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
String received = clientEndpoint.textMessages.poll(timeout, TimeUnit.SECONDS);
assertThat(received, equalTo(message));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SingleOnMessageTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SingleOnMessageTest.java
index 98e87039aaa..ae759521335 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SingleOnMessageTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/SingleOnMessageTest.java
@@ -23,12 +23,12 @@ import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -84,11 +84,10 @@ public class SingleOnMessageTest
assertTrue(serverSocket.openLatch.await(5, TimeUnit.SECONDS));
// The server sends a sequence of Binary and Text messages
- RemoteEndpoint remote = serverSocket.session.getRemote();
- remote.sendBytes(BufferUtil.toBuffer("this should get rejected"));
- remote.sendString("WebSocket_Data0");
- remote.sendString("WebSocket_Data1");
- serverSocket.session.close(StatusCode.NORMAL, "test complete");
+ serverSocket.session.sendBinary(BufferUtil.toBuffer("this should get rejected"), Callback.NOOP);
+ serverSocket.session.sendText("WebSocket_Data0", Callback.NOOP);
+ serverSocket.session.sendText("WebSocket_Data1", Callback.NOOP);
+ serverSocket.session.close(StatusCode.NORMAL, "test complete", Callback.NOOP);
// The client receives the messages and has discarded the binary message.
assertThat(handler.messages.poll(5, TimeUnit.SECONDS), is("WebSocket_Data0"));
@@ -107,13 +106,12 @@ public class SingleOnMessageTest
assertTrue(serverSocket.openLatch.await(5, TimeUnit.SECONDS));
// The server sends a sequence of Binary and Text messages
- RemoteEndpoint remote = serverSocket.session.getRemote();
- remote.sendString("this should get rejected");
- remote.sendBytes(BufferUtil.toBuffer("WebSocket_Data0"));
- remote.sendBytes(BufferUtil.toBuffer("WebSocket_Data1"));
- serverSocket.session.close(StatusCode.NORMAL, "test complete");
+ serverSocket.session.sendText("this should get rejected", Callback.NOOP);
+ serverSocket.session.sendBinary(BufferUtil.toBuffer("WebSocket_Data0"), Callback.NOOP);
+ serverSocket.session.sendBinary(BufferUtil.toBuffer("WebSocket_Data1"), Callback.NOOP);
+ serverSocket.session.close(StatusCode.NORMAL, "test complete", Callback.NOOP);
- // The client receives the messages and has discarded the binary message.
+ // The client receives the messages and has discarded the text message.
assertThat(handler.messages.poll(5, TimeUnit.SECONDS), is(BufferUtil.toBuffer("WebSocket_Data0")));
assertThat(handler.messages.poll(5, TimeUnit.SECONDS), is(BufferUtil.toBuffer("WebSocket_Data1")));
assertTrue(handler.closeLatch.await(5, TimeUnit.SECONDS));
@@ -139,9 +137,10 @@ public class SingleOnMessageTest
final BlockingArrayQueue messages = new BlockingArrayQueue<>();
@OnWebSocketMessage
- public void onMessage(byte[] array, int offset, int length)
+ public void onMessage(ByteBuffer payload, Callback callback)
{
- messages.add(BufferUtil.toBuffer(array, offset, length));
+ messages.add(BufferUtil.copy(payload));
+ callback.succeed();
}
}
@@ -162,8 +161,8 @@ public class SingleOnMessageTest
this.closeLatch.countDown();
}
- @OnWebSocketConnect
- public void onConnect(Session session)
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
this.session = session;
this.openLatch.countDown();
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketStatsTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketStatsTest.java
index 054f0193603..a10fcd14d36 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketStatsTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketStatsTest.java
@@ -27,6 +27,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.core.CloseStatus;
@@ -123,7 +124,7 @@ public class WebSocketStatsTest
{
for (int i = 0; i < numMessages; i++)
{
- session.getRemote().sendString(msgText);
+ session.sendText(msgText, Callback.NOOP);
}
}
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketStopTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketStopTest.java
index fde36bc70ef..7ae24bedda4 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketStopTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketStopTest.java
@@ -13,14 +13,15 @@
package org.eclipse.jetty.websocket.tests;
-import java.io.IOException;
import java.net.URI;
import java.nio.channels.ClosedChannelException;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
@@ -100,9 +101,9 @@ public class WebSocketStopTest
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.addExtensions("permessage-deflate");
Session session = client.connect(clientSocket, uri, upgradeRequest).get(5, TimeUnit.SECONDS);
- clientSocket.session.getRemote().sendString("init deflater");
+ clientSocket.session.sendText("init deflater", Callback.NOOP);
assertThat(serverSocket.textMessages.poll(5, TimeUnit.SECONDS), is("init deflater"));
- session.close(StatusCode.NORMAL, null);
+ session.close(StatusCode.NORMAL, null, Callback.NOOP);
// make sure both sides are closed
clientSocket.session.close();
@@ -113,8 +114,10 @@ public class WebSocketStopTest
assertThat(clientSocket.closeCode, is(StatusCode.NORMAL));
assertThat(serverSocket.closeCode, is(StatusCode.NORMAL));
- IOException error = assertThrows(IOException.class,
- () -> session.getRemote().sendString("this should fail before ExtensionStack"));
+ ExecutionException error = assertThrows(ExecutionException.class, () ->
+ Callback.Completable.with(c -> session.sendText("this should fail before ExtensionStack", c))
+ .get(5, TimeUnit.SECONDS)
+ );
assertThat(error.getCause(), instanceOf(ClosedChannelException.class));
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/autobahn/JettyAutobahnClient.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/autobahn/JettyAutobahnClient.java
index 519e1c3f2f1..acbc20e61af 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/autobahn/JettyAutobahnClient.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/autobahn/JettyAutobahnClient.java
@@ -23,6 +23,7 @@ import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.util.Jetty;
import org.eclipse.jetty.util.UrlEncoded;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -157,7 +158,7 @@ public class JettyAutobahnClient
if (waitForUpgrade(wsUri, response))
{
String msg = onCaseCount.textMessages.poll(10, TimeUnit.SECONDS);
- onCaseCount.session.close(StatusCode.SHUTDOWN, null);
+ onCaseCount.session.close(StatusCode.SHUTDOWN, null, Callback.NOOP);
assertTrue(onCaseCount.closeLatch.await(2, TimeUnit.SECONDS));
assertNotNull(msg);
return Integer.decode(msg);
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/BadNetworkTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/BadNetworkTest.java
index 0585add746e..8d2e538f280 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/BadNetworkTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/BadNetworkTest.java
@@ -13,7 +13,6 @@
package org.eclipse.jetty.websocket.tests.client;
-import java.io.IOException;
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.Future;
@@ -22,9 +21,9 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeHandler;
@@ -122,7 +121,7 @@ public class BadNetworkTest
Session session = future.get(30, TimeUnit.SECONDS);
// Have server disconnect abruptly
- session.getRemote().sendString("abort");
+ session.sendText("abort", Callback.NOOP);
// Client Socket should see a close event, with status NO_CLOSE
// This event is automatically supplied by the underlying WebSocketClientConnection
@@ -130,55 +129,36 @@ public class BadNetworkTest
wsocket.assertReceivedCloseEvent(5000, is(StatusCode.NO_CLOSE), containsString(""));
}
- public static class ServerEndpoint implements WebSocketListener
+ public static class ServerEndpoint implements Session.Listener.AutoDemanding
{
private static final Logger LOG = LoggerFactory.getLogger(ClientCloseTest.ServerEndpoint.class);
private Session session;
@Override
- public void onWebSocketBinary(byte[] payload, int offset, int len)
+ public void onWebSocketOpen(Session session)
{
+ this.session = session;
}
@Override
public void onWebSocketText(String message)
{
- try
+ if (message.equals("abort"))
{
- if (message.equals("abort"))
- {
- session.disconnect();
- }
- else
- {
- // simple echo
- session.getRemote().sendString(message);
- }
+ session.disconnect();
}
- catch (IOException e)
+ else
{
- LOG.warn("Failed to send string", e);
+ // simple echo
+ session.sendText(message, Callback.NOOP);
}
}
- @Override
- public void onWebSocketClose(int statusCode, String reason)
- {
- }
-
- @Override
- public void onWebSocketConnect(Session session)
- {
- this.session = session;
- }
-
@Override
public void onWebSocketError(Throwable cause)
{
if (LOG.isDebugEnabled())
- {
LOG.debug("ServerEndpoint error", cause);
- }
}
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientCloseTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientCloseTest.java
index ad13d3eee5c..ecf61d5e5af 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientCloseTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientCloseTest.java
@@ -28,11 +28,10 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BlockingArrayQueue;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Frame;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.api.WebSocketFrameListener;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
import org.eclipse.jetty.websocket.api.exceptions.MessageTooLargeException;
import org.eclipse.jetty.websocket.api.exceptions.WebSocketTimeoutException;
import org.eclipse.jetty.websocket.api.util.WSURI;
@@ -74,7 +73,7 @@ public class ClientCloseTest
{
// Send message from client to server
final String echoMsg = "echo-test";
- clientSocket.getRemote().sendString(echoMsg);
+ clientSocket.getSession().sendText(echoMsg, Callback.NOOP);
// Verify received message
String recvMsg = clientSocket.messageQueue.poll(5, SECONDS);
@@ -159,7 +158,8 @@ public class ClientCloseTest
// client sends close frame (code 1000, normal)
final String origCloseReason = "send-more-frames";
- clientSocket.getSession().close(StatusCode.NORMAL, origCloseReason);
+ Session session = clientSocket.getSession();
+ session.close(StatusCode.NORMAL, origCloseReason, Callback.NOOP);
// Verify received messages
String recvMsg = clientSocket.messageQueue.poll(5, SECONDS);
@@ -193,7 +193,8 @@ public class ClientCloseTest
// client confirms connection via echo
confirmConnection(clientSocket, clientConnectFuture);
- clientSocket.getSession().getRemote().sendString("too-large-message");
+ Session session = clientSocket.getSession();
+ session.sendText("too-large-message", Callback.NOOP);
clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.MESSAGE_TOO_LARGE), containsString("Text message too large"));
// client should have noticed the error
@@ -224,7 +225,8 @@ public class ClientCloseTest
// client sends close frame (triggering server connection abort)
final String origCloseReason = "abort";
- clientSocket.getSession().close(StatusCode.NORMAL, origCloseReason);
+ Session session = clientSocket.getSession();
+ session.close(StatusCode.NORMAL, origCloseReason, Callback.NOOP);
// client reads -1 (EOF)
// client triggers close event on client ws-endpoint
@@ -255,7 +257,8 @@ public class ClientCloseTest
// client sends close frame
final String origCloseReason = "sleep|2500";
- clientSocket.getSession().close(StatusCode.NORMAL, origCloseReason);
+ Session session = clientSocket.getSession();
+ session.close(StatusCode.NORMAL, origCloseReason, Callback.NOOP);
// client close should occur
clientSocket.assertReceivedCloseEvent(clientTimeout * 2,
@@ -283,8 +286,10 @@ public class ClientCloseTest
confirmConnection(clientSocket, clientConnectFuture);
// Close twice, first close should succeed and second close is a NOOP
- clientSocket.getSession().close(StatusCode.NORMAL, "close1");
- clientSocket.getSession().close(StatusCode.NO_CODE, "close2");
+ Session session1 = clientSocket.getSession();
+ session1.close(StatusCode.NORMAL, "close1", Callback.NOOP);
+ Session session = clientSocket.getSession();
+ session.close(StatusCode.NO_CODE, "close2", Callback.NOOP);
// Second close is ignored, we are notified of the first close.
clientSocket.assertReceivedCloseEvent(5000, is(StatusCode.NORMAL), containsString("close1"));
@@ -324,7 +329,8 @@ public class ClientCloseTest
// block all the server threads
for (int i = 0; i < sessionCount; i++)
{
- clientSockets.get(i).getSession().getRemote().sendString("block");
+ Session session = clientSockets.get(i).getSession();
+ session.sendText("block", Callback.NOOP);
}
assertTimeoutPreemptively(ofSeconds(5), () ->
@@ -375,7 +381,8 @@ public class ClientCloseTest
try
{
// Block on the server so that the server does not detect a read failure
- clientSocket.getSession().getRemote().sendString("block");
+ Session session1 = clientSocket.getSession();
+ session1.sendText("block", Callback.NOOP);
// setup client endpoint for write failure (test only)
EndPoint endp = clientSocket.getEndPoint();
@@ -384,7 +391,8 @@ public class ClientCloseTest
// client enqueue close frame
// should result in a client write failure
final String origCloseReason = "Normal Close from Client";
- clientSocket.getSession().close(StatusCode.NORMAL, origCloseReason);
+ Session session = clientSocket.getSession();
+ session.close(StatusCode.NORMAL, origCloseReason, Callback.NOOP);
assertThat("OnError Latch", clientSocket.errorLatch.await(2, SECONDS), is(true));
assertThat("OnError", clientSocket.error.get(), instanceOf(EofException.class));
@@ -405,15 +413,16 @@ public class ClientCloseTest
}
}
- public static class ServerEndpoint implements WebSocketFrameListener, WebSocketListener
+ public static class ServerEndpoint implements Session.Listener.AutoDemanding
{
private static final Logger LOG = LoggerFactory.getLogger(ServerEndpoint.class);
private Session session;
CountDownLatch block = new CountDownLatch(1);
@Override
- public void onWebSocketBinary(byte[] payload, int offset, int len)
+ public void onWebSocketOpen(Session session)
{
+ this.session = session;
}
@Override
@@ -427,7 +436,7 @@ public class ClientCloseTest
byte[] buf = new byte[1024 * 1024];
Arrays.fill(buf, (byte)'x');
String bigmsg = new String(buf, UTF_8);
- session.getRemote().sendString(bigmsg);
+ session.sendText(bigmsg, Callback.NOOP);
}
else if (message.equals("block"))
{
@@ -438,7 +447,7 @@ public class ClientCloseTest
else
{
// simple echo
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
}
}
catch (Throwable t)
@@ -448,17 +457,6 @@ public class ClientCloseTest
}
}
- @Override
- public void onWebSocketClose(int statusCode, String reason)
- {
- }
-
- @Override
- public void onWebSocketConnect(Session session)
- {
- this.session = session;
- }
-
@Override
public void onWebSocketError(Throwable cause)
{
@@ -467,7 +465,7 @@ public class ClientCloseTest
}
@Override
- public void onWebSocketFrame(Frame frame)
+ public void onWebSocketFrame(Frame frame, Callback callback)
{
if (frame.getOpCode() == OpCode.CLOSE)
{
@@ -478,12 +476,12 @@ public class ClientCloseTest
{
try
{
- session.getRemote().sendString("Hello");
- session.getRemote().sendString("World");
+ session.sendText("Hello", Callback.NOOP);
+ session.sendText("World", Callback.NOOP);
}
- catch (Throwable ignore)
+ catch (Throwable x)
{
- LOG.debug("OOPS", ignore);
+ LOG.debug("OOPS", x);
}
}
else if (reason.equals("abort"))
@@ -494,9 +492,9 @@ public class ClientCloseTest
LOG.info("Server aborting session abruptly");
session.disconnect();
}
- catch (Throwable ignore)
+ catch (Throwable x)
{
- LOG.trace("IGNORED", ignore);
+ LOG.trace("IGNORED", x);
}
}
else if (reason.startsWith("sleep|"))
@@ -508,12 +506,13 @@ public class ClientCloseTest
LOG.info("Server Sleeping for {} ms", timeMs);
TimeUnit.MILLISECONDS.sleep(timeMs);
}
- catch (InterruptedException ignore)
+ catch (InterruptedException x)
{
- LOG.trace("IGNORED", ignore);
+ LOG.trace("IGNORED", x);
}
}
}
+ callback.succeed();
}
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientConfigTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientConfigTest.java
index e0391f2c43c..2c7547e5840 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientConfigTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientConfigTest.java
@@ -14,6 +14,7 @@
package org.eclipse.jetty.websocket.tests.client;
import java.net.URI;
+import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -23,7 +24,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.websocket.api.BatchMode;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@@ -62,7 +63,7 @@ public class ClientConfigTest
public static Stream data()
{
- return Stream.of("clientConfig", "annotatedConfig", "sessionConfig").map(Arguments::of);
+ return Stream.of("clientConfig", "sessionConfig").map(Arguments::of);
}
@BeforeEach
@@ -93,11 +94,6 @@ public class ClientConfigTest
server.stop();
}
- @WebSocket(idleTimeout = IDLE_TIMEOUT, maxTextMessageSize = MAX_MESSAGE_SIZE, maxBinaryMessageSize = MAX_MESSAGE_SIZE, inputBufferSize = INPUT_BUFFER_SIZE, batchMode = BatchMode.ON)
- public static class AnnotatedConfigEndpoint extends EventSocket
- {
- }
-
@WebSocket
public static class SessionConfigEndpoint extends EventSocket
{
@@ -124,7 +120,6 @@ public class ClientConfigTest
client.setMaxTextMessageSize(MAX_MESSAGE_SIZE);
yield new EventSocket();
}
- case "annotatedConfig" -> new AnnotatedConfigEndpoint();
case "sessionConfig" -> new SessionConfigEndpoint();
default -> throw new IllegalStateException();
};
@@ -162,7 +157,8 @@ public class ClientConfigTest
CompletableFuture connect = client.connect(clientEndpoint, uri);
connect.get(5, TimeUnit.SECONDS);
- clientEndpoint.session.getRemote().sendBytes(BufferUtil.toBuffer(MESSAGE));
+ ByteBuffer buffer = BufferUtil.toBuffer(MESSAGE);
+ clientEndpoint.session.sendBinary(buffer, Callback.NOOP);
assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(clientEndpoint.error, instanceOf(MessageTooLargeException.class));
@@ -180,7 +176,7 @@ public class ClientConfigTest
CompletableFuture connect = client.connect(clientEndpoint, uri);
connect.get(5, TimeUnit.SECONDS);
- clientEndpoint.session.getRemote().sendString("hello world");
+ clientEndpoint.session.sendText("hello world", Callback.NOOP);
Thread.sleep(IDLE_TIMEOUT + 500);
assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
@@ -199,7 +195,7 @@ public class ClientConfigTest
CompletableFuture connect = client.connect(clientEndpoint, uri);
connect.get(5, TimeUnit.SECONDS);
- clientEndpoint.session.getRemote().sendString(MESSAGE);
+ clientEndpoint.session.sendText(MESSAGE, Callback.NOOP);
assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(clientEndpoint.error, instanceOf(MessageTooLargeException.class));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientConnectTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientConnectTest.java
index 89028aca048..3a570c1acc3 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientConnectTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientConnectTest.java
@@ -89,7 +89,7 @@ public class ClientConnectTest
assertThat("Error", capcause, errorMatcher);
// Validate that websocket didn't see an open event
- assertThat("Open Latch", wsocket.openLatch.getCount(), is(1L));
+ assertThat("Open Latch", wsocket.connectLatch.getCount(), is(1L));
// Return the captured cause
return (E)capcause;
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientSessionsTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientSessionsTest.java
index 8252280be0b..d666fda82b7 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientSessionsTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientSessionsTest.java
@@ -23,7 +23,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
@@ -118,8 +118,7 @@ public class ClientSessionsTest
Collection sessions = client.getOpenSessions();
assertThat("client.connectionManager.sessions.size", sessions.size(), is(1));
- RemoteEndpoint remote = sess.getRemote();
- remote.sendString("Hello World!");
+ sess.sendText("Hello World!", Callback.NOOP);
Collection open = client.getOpenSessions();
assertThat("(Before Close) Open Sessions.size", open.size(), is(1));
@@ -127,7 +126,7 @@ public class ClientSessionsTest
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Message", received, containsString("Hello World!"));
- sess.close(StatusCode.NORMAL, null);
+ sess.close(StatusCode.NORMAL, null, Callback.NOOP);
}
cliSock.assertReceivedCloseEvent(30000, is(StatusCode.NORMAL));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientWriteThread.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientWriteThread.java
index c8636e22c50..710ddc02f56 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientWriteThread.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientWriteThread.java
@@ -16,10 +16,8 @@ package org.eclipse.jetty.websocket.tests.client;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-import org.eclipse.jetty.websocket.api.BatchMode;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.tests.util.FutureWriteCallback;
+import org.eclipse.jetty.websocket.tests.util.FutureCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -60,12 +58,11 @@ public class ClientWriteThread extends Thread
{
LOG.debug("Writing {} messages to {}", messageCount, session);
LOG.debug("Artificial Slowness {} ms", slowness);
- FutureWriteCallback lastMessage = null;
- RemoteEndpoint remote = session.getRemote();
+ FutureCallback lastMessage = null;
while (m.get() < messageCount)
{
- lastMessage = new FutureWriteCallback();
- remote.sendString(message + "/" + m.get() + "/", lastMessage);
+ lastMessage = new FutureCallback();
+ session.sendText(message + "/" + m.get() + "/", lastMessage);
m.incrementAndGet();
@@ -74,8 +71,6 @@ public class ClientWriteThread extends Thread
TimeUnit.MILLISECONDS.sleep(slowness);
}
}
- if (remote.getBatchMode() == BatchMode.ON)
- remote.flush();
// block on write of last message
if (lastMessage != null)
lastMessage.get(2, TimeUnit.MINUTES); // block on write
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ConnectFutureTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ConnectFutureTest.java
index c29cdcc7639..1ecf68ef5fd 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ConnectFutureTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ConnectFutureTest.java
@@ -27,6 +27,7 @@ import org.eclipse.jetty.client.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
@@ -113,7 +114,7 @@ public class ConnectFutureTest
assertTrue(connect.cancel(true));
assertThrows(CancellationException.class, () -> connect.get(5, TimeUnit.SECONDS));
exitCreator.countDown();
- assertFalse(clientSocket.openLatch.await(1, TimeUnit.SECONDS));
+ assertFalse(clientSocket.connectLatch.await(1, TimeUnit.SECONDS));
Throwable error = clientSocket.error.get();
assertThat(error, instanceOf(UpgradeException.class));
@@ -156,7 +157,7 @@ public class ConnectFutureTest
assertTrue(connect.cancel(true));
assertThrows(CancellationException.class, () -> connect.get(5, TimeUnit.SECONDS));
exitListener.countDown();
- assertTrue(clientSocket.openLatch.await(5, TimeUnit.SECONDS));
+ assertTrue(clientSocket.connectLatch.await(5, TimeUnit.SECONDS));
assertTrue(clientSocket.errorLatch.await(5, TimeUnit.SECONDS));
assertThat(clientSocket.error.get(), instanceOf(CancellationException.class));
}
@@ -196,7 +197,7 @@ public class ConnectFutureTest
assertTrue(connect.cancel(true));
assertThrows(CancellationException.class, () -> connect.get(5, TimeUnit.SECONDS));
exitListener.countDown();
- assertTrue(clientSocket.openLatch.await(5, TimeUnit.SECONDS));
+ assertTrue(clientSocket.connectLatch.await(5, TimeUnit.SECONDS));
assertTrue(clientSocket.errorLatch.await(5, TimeUnit.SECONDS));
assertThat(clientSocket.error.get(), instanceOf(CancellationException.class));
}
@@ -208,16 +209,16 @@ public class ConnectFutureTest
wsHandler.configure(container ->
container.addMapping("/", (upgradeRequest, upgradeResponse, callback) -> new EchoSocket())));
- CountDownLatch exitOnOpen = new CountDownLatch(1);
+ CountDownLatch exitOnConnect = new CountDownLatch(1);
CloseTrackingEndpoint clientSocket = new CloseTrackingEndpoint()
{
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
try
{
- super.onWebSocketConnect(session);
- exitOnOpen.await();
+ super.onWebSocketOpen(session);
+ exitOnConnect.await();
}
catch (InterruptedException e)
{
@@ -228,9 +229,9 @@ public class ConnectFutureTest
// Abort during the call to onOpened. This is after the connection upgrade, but before future completion.
Future connect = client.connect(clientSocket, WSURI.toWebsocket(server.getURI()));
- assertTrue(clientSocket.openLatch.await(5, TimeUnit.SECONDS));
+ assertTrue(clientSocket.connectLatch.await(5, TimeUnit.SECONDS));
assertTrue(connect.cancel(true));
- exitOnOpen.countDown();
+ exitOnConnect.countDown();
// We got an error on the WebSocket endpoint and an error from the future.
assertTrue(clientSocket.errorLatch.await(5, TimeUnit.SECONDS));
@@ -249,8 +250,9 @@ public class ConnectFutureTest
Session session = connect.get(5, TimeUnit.SECONDS);
// If we can send and receive messages the future has been completed.
- assertTrue(clientSocket.openLatch.await(5, TimeUnit.SECONDS));
- clientSocket.getSession().getRemote().sendString("hello");
+ assertTrue(clientSocket.connectLatch.await(5, TimeUnit.SECONDS));
+ Session session1 = clientSocket.getSession();
+ session1.sendText("hello", Callback.NOOP);
assertThat(clientSocket.messageQueue.poll(5, TimeUnit.SECONDS), Matchers.is("hello"));
// After it has been completed we should not get any errors from cancelling it.
@@ -345,16 +347,16 @@ public class ConnectFutureTest
wsHandler.configure(container ->
container.addMapping("/", (upgradeRequest, upgradeResponse, callback) -> new EchoSocket())));
- CountDownLatch exitOnOpen = new CountDownLatch(1);
+ CountDownLatch exitOnConnect = new CountDownLatch(1);
CloseTrackingEndpoint clientSocket = new CloseTrackingEndpoint()
{
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
try
{
- super.onWebSocketConnect(session);
- exitOnOpen.await();
+ super.onWebSocketOpen(session);
+ exitOnConnect.await();
}
catch (InterruptedException e)
{
@@ -365,9 +367,9 @@ public class ConnectFutureTest
// Complete the CompletableFuture with an exception the during the call to onOpened.
CompletableFuture connect = client.connect(clientSocket, WSURI.toWebsocket(server.getURI()));
- assertTrue(clientSocket.openLatch.await(5, TimeUnit.SECONDS));
+ assertTrue(clientSocket.connectLatch.await(5, TimeUnit.SECONDS));
assertTrue(connect.completeExceptionally(new WebSocketException("custom exception")));
- exitOnOpen.countDown();
+ exitOnConnect.countDown();
// Exception from the future is correct.
ExecutionException futureError = assertThrows(ExecutionException.class, () -> connect.get(5, TimeUnit.SECONDS));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/SlowClientTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/SlowClientTest.java
index f54636e62cd..326a4781dab 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/SlowClientTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/SlowClientTest.java
@@ -20,6 +20,7 @@ import java.util.concurrent.Future;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.util.WSURI;
@@ -104,7 +105,8 @@ public class SlowClientTest
writer.join();
// Close
- clientEndpoint.getSession().close(StatusCode.NORMAL, "Done");
+ Session session = clientEndpoint.getSession();
+ session.close(StatusCode.NORMAL, "Done", Callback.NOOP);
// confirm close received on server
clientEndpoint.assertReceivedCloseEvent(10000, is(StatusCode.NORMAL), containsString("Done"));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/WebSocketClientTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/WebSocketClientTest.java
index 9744137da86..0806c4c0981 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/WebSocketClientTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/WebSocketClientTest.java
@@ -30,7 +30,7 @@ import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.util.WSURI;
@@ -42,7 +42,7 @@ import org.eclipse.jetty.websocket.tests.CloseTrackingEndpoint;
import org.eclipse.jetty.websocket.tests.ConnectMessageEndpoint;
import org.eclipse.jetty.websocket.tests.EchoSocket;
import org.eclipse.jetty.websocket.tests.ParamsEndpoint;
-import org.eclipse.jetty.websocket.tests.util.FutureWriteCallback;
+import org.eclipse.jetty.websocket.tests.util.FutureCallback;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -153,8 +153,7 @@ public class WebSocketClientTest
Collection sessions = client.getOpenSessions();
assertThat("client.sessions.size", sessions.size(), is(1));
- RemoteEndpoint remote = cliSock.getSession().getRemote();
- remote.sendString("Hello World!");
+ cliSock.getSession().sendText("Hello World!", Callback.NOOP);
// wait for response from server
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
@@ -184,10 +183,9 @@ public class WebSocketClientTest
Collection sessions = client.getOpenSessions();
assertThat("client.sessions.size", sessions.size(), is(1));
- RemoteEndpoint remote = cliSock.getSession().getRemote();
- remote.sendPartialString("Hello", false);
- remote.sendPartialString(" ", false);
- remote.sendPartialString("World", true);
+ cliSock.getSession().sendPartialText("Hello", false, Callback.NOOP);
+ cliSock.getSession().sendPartialText(" ", false, Callback.NOOP);
+ cliSock.getSession().sendPartialText("World", true, Callback.NOOP);
// wait for response from server
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
@@ -217,10 +215,9 @@ public class WebSocketClientTest
Collection sessions = client.getOpenSessions();
assertThat("client.sessions.size", sessions.size(), is(1));
- RemoteEndpoint remote = cliSock.getSession().getRemote();
- remote.sendPartialString("Hello", false);
- remote.sendPartialString(" ", false);
- remote.sendPartialString("World", true);
+ cliSock.getSession().sendPartialText("Hello", false, Callback.NOOP);
+ cliSock.getSession().sendPartialText(" ", false, Callback.NOOP);
+ cliSock.getSession().sendPartialText("World", true, Callback.NOOP);
String[] parts = {
"The difference between the right word ",
@@ -228,9 +225,15 @@ public class WebSocketClientTest
"between lightning and a lightning bug."
};
- remote.sendPartialBytes(BufferUtil.toBuffer(parts[0]), false);
- remote.sendPartialBytes(BufferUtil.toBuffer(parts[1]), false);
- remote.sendPartialBytes(BufferUtil.toBuffer(parts[2]), true);
+ Session session2 = cliSock.getSession();
+ ByteBuffer b2 = BufferUtil.toBuffer(parts[0]);
+ session2.sendPartialBinary(b2, false, Callback.NOOP);
+ Session session1 = cliSock.getSession();
+ ByteBuffer b1 = BufferUtil.toBuffer(parts[1]);
+ session1.sendPartialBinary(b1, false, Callback.NOOP);
+ Session session = cliSock.getSession();
+ ByteBuffer b = BufferUtil.toBuffer(parts[2]);
+ session.sendPartialBinary(b, true, Callback.NOOP);
// wait for response from server
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
@@ -264,9 +267,9 @@ public class WebSocketClientTest
Collection sessions = client.getOpenSessions();
assertThat("client.sessions.size", sessions.size(), is(1));
- FutureWriteCallback callback = new FutureWriteCallback();
+ FutureCallback callback = new FutureCallback();
- cliSock.getSession().getRemote().sendString("Hello World!", callback);
+ cliSock.getSession().sendText("Hello World!", callback);
callback.get(5, TimeUnit.SECONDS);
// wait for response from server
@@ -295,7 +298,7 @@ public class WebSocketClientTest
// wait for message from server
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
- assertThat("Message", received, containsString("Greeting from onConnect"));
+ assertThat("Message", received, containsString("Greeting from onOpen"));
}
}
@@ -313,10 +316,10 @@ public class WebSocketClientTest
try (Session sess = future.get(5, TimeUnit.SECONDS))
{
- Assertions.assertTrue(cliSock.openLatch.await(1, TimeUnit.SECONDS));
+ Assertions.assertTrue(cliSock.connectLatch.await(1, TimeUnit.SECONDS));
- InetSocketAddress local = (InetSocketAddress)cliSock.getSession().getLocalAddress();
- InetSocketAddress remote = (InetSocketAddress)cliSock.getSession().getRemoteAddress();
+ InetSocketAddress local = (InetSocketAddress)cliSock.getSession().getLocalSocketAddress();
+ InetSocketAddress remote = (InetSocketAddress)cliSock.getSession().getRemoteSocketAddress();
assertThat("Local Socket Address", local, notNullValue());
assertThat("Remote Socket Address", remote, notNullValue());
@@ -359,7 +362,7 @@ public class WebSocketClientTest
Arrays.fill(buf, (byte)'x');
String msg = StringUtil.toUTF8String(buf, 0, buf.length);
- sess.getRemote().sendString(msg);
+ sess.sendText(msg, Callback.NOOP);
// wait for message from server
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/AbstractAnnotatedListener.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/AbstractAnnotatedListener.java
index 8d7d2253b70..e7e0ccb374e 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/AbstractAnnotatedListener.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/AbstractAnnotatedListener.java
@@ -13,12 +13,12 @@
package org.eclipse.jetty.websocket.tests.listeners;
-import java.io.IOException;
import java.nio.ByteBuffer;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@WebSocket
@@ -26,8 +26,8 @@ public class AbstractAnnotatedListener
{
protected Session _session;
- @OnWebSocketConnect
- public void onWebSocketConnect(Session session)
+ @OnWebSocketOpen
+ public void onWebSocketOpen(Session session)
{
_session = session;
}
@@ -40,25 +40,11 @@ public class AbstractAnnotatedListener
public void sendText(String message, boolean last)
{
- try
- {
- _session.getRemote().sendPartialString(message, last);
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
+ _session.sendPartialText(message, last, Callback.NOOP);
}
public void sendBinary(ByteBuffer message, boolean last)
{
- try
- {
- _session.getRemote().sendPartialBytes(message, last);
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
+ _session.sendPartialBinary(message, last, Callback.NOOP);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/AbstractListener.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/AbstractListener.java
deleted file mode 100644
index 856b94ed51a..00000000000
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/AbstractListener.java
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.tests.listeners;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketConnectionListener;
-
-public class AbstractListener implements WebSocketConnectionListener
-{
- protected Session _session;
-
- @Override
- public void onWebSocketConnect(Session session)
- {
- _session = session;
- }
-
- @Override
- public void onWebSocketError(Throwable thr)
- {
- thr.printStackTrace();
- }
-
- public void sendText(String message, boolean last)
- {
- try
- {
- _session.getRemote().sendPartialString(message, last);
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- public void sendBinary(ByteBuffer message, boolean last)
- {
- try
- {
- _session.getRemote().sendPartialBytes(message, last);
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/BinaryListeners.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/BinaryListeners.java
index e1071e6de32..06999f10c0e 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/BinaryListeners.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/BinaryListeners.java
@@ -20,9 +20,8 @@ import java.util.stream.Stream;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
-import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.junit.jupiter.params.provider.Arguments;
@@ -35,28 +34,48 @@ public class BinaryListeners
OffsetByteArrayWholeListener.class,
OffsetByteBufferPartialListener.class,
AnnotatedByteBufferWholeListener.class,
- AnnotatedByteArrayWholeListener.class,
- AnnotatedOffsetByteArrayWholeListener.class,
AnnotatedInputStreamWholeListener.class,
AnnotatedReverseArgumentPartialListener.class
).map(Arguments::of);
}
- public static class OffsetByteArrayWholeListener extends AbstractListener implements WebSocketListener
+ public static class OffsetByteArrayWholeListener extends Session.Listener.Abstract
{
@Override
- public void onWebSocketBinary(byte[] payload, int offset, int len)
+ public void onWebSocketOpen(Session session)
{
- sendBinary(BufferUtil.toBuffer(payload, offset, len), true);
+ super.onWebSocketOpen(session);
+ session.demand();
+ }
+
+ @Override
+ public void onWebSocketBinary(ByteBuffer payload, Callback callback)
+ {
+ getSession().sendPartialBinary(payload, true, Callback.from(() ->
+ {
+ callback.succeed();
+ getSession().demand();
+ }, callback::fail));
}
}
- public static class OffsetByteBufferPartialListener extends AbstractListener implements WebSocketPartialListener
+ public static class OffsetByteBufferPartialListener extends Session.Listener.Abstract
{
@Override
- public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin)
+ public void onWebSocketOpen(Session session)
{
- sendBinary(payload, fin);
+ super.onWebSocketOpen(session);
+ session.demand();
+ }
+
+ @Override
+ public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin, Callback callback)
+ {
+ getSession().sendPartialBinary(payload, fin, Callback.from(() ->
+ {
+ callback.succeed();
+ getSession().demand();
+ }, callback::fail));
}
}
@@ -64,29 +83,9 @@ public class BinaryListeners
public static class AnnotatedByteBufferWholeListener extends AbstractAnnotatedListener
{
@OnWebSocketMessage
- public void onMessage(ByteBuffer message)
+ public void onMessage(ByteBuffer message, Callback callback)
{
- sendBinary(message, true);
- }
- }
-
- @WebSocket
- public static class AnnotatedByteArrayWholeListener extends AbstractAnnotatedListener
- {
- @OnWebSocketMessage
- public void onMessage(byte[] message)
- {
- sendBinary(BufferUtil.toBuffer(message), true);
- }
- }
-
- @WebSocket
- public static class AnnotatedOffsetByteArrayWholeListener extends AbstractAnnotatedListener
- {
- @OnWebSocketMessage
- public void onMessage(byte[] message, int offset, int length)
- {
- sendBinary(BufferUtil.toBuffer(message, offset, length), true);
+ _session.sendPartialBinary(message, true, callback);
}
}
@@ -104,9 +103,9 @@ public class BinaryListeners
public static class AnnotatedReverseArgumentPartialListener extends AbstractAnnotatedListener
{
@OnWebSocketMessage
- public void onMessage(Session session, ByteBuffer message)
+ public void onMessage(Session session, ByteBuffer message, Callback callback)
{
- sendBinary(message, true);
+ _session.sendPartialBinary(message, true, callback);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/TextListeners.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/TextListeners.java
index 873a89761b1..7c4b8129baf 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/TextListeners.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/TextListeners.java
@@ -18,9 +18,8 @@ import java.io.Reader;
import java.util.stream.Stream;
import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
-import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.junit.jupiter.params.provider.Arguments;
@@ -38,21 +37,41 @@ public class TextListeners
).map(Arguments::of);
}
- public static class StringWholeListener extends AbstractListener implements WebSocketListener
+ public static class StringWholeListener extends Session.Listener.Abstract
{
+ @Override
+ public void onWebSocketOpen(Session session)
+ {
+ super.onWebSocketOpen(session);
+ session.demand();
+ }
+
@Override
public void onWebSocketText(String message)
{
- sendText(message, true);
+ getSession().sendPartialText(message, true, Callback.from(getSession()::demand, x ->
+ {
+ throw new RuntimeException(x);
+ }));
}
}
- public static class StringPartialListener extends AbstractListener implements WebSocketPartialListener
+ public static class StringPartialListener extends Session.Listener.Abstract
{
+ @Override
+ public void onWebSocketOpen(Session session)
+ {
+ super.onWebSocketOpen(session);
+ session.demand();
+ }
+
@Override
public void onWebSocketPartialText(String message, boolean fin)
{
- sendText(message, fin);
+ getSession().sendPartialText(message, fin, Callback.from(getSession()::demand, x ->
+ {
+ throw new RuntimeException(x);
+ }));
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/WebSocketListenerTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/WebSocketListenerTest.java
index 0470c8d1099..e552dfb4e5c 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/WebSocketListenerTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/listeners/WebSocketListenerTest.java
@@ -27,9 +27,9 @@ import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeHandler;
import org.eclipse.jetty.websocket.tests.EchoSocket;
@@ -99,12 +99,12 @@ public class WebSocketListenerTest
// Send and receive echo on client.
String payload = "hello world";
- clientEndpoint.session.getRemote().sendString(payload);
+ clientEndpoint.session.sendText(payload, Callback.NOOP);
String echoMessage = clientEndpoint.textMessages.poll(5, TimeUnit.SECONDS);
assertThat(echoMessage, is(payload));
// Close normally.
- clientEndpoint.session.close(StatusCode.NORMAL, "standard close");
+ clientEndpoint.session.close(StatusCode.NORMAL, "standard close", Callback.NOOP);
assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(clientEndpoint.closeCode, is(StatusCode.NORMAL));
assertThat(clientEndpoint.closeReason, is("standard close"));
@@ -119,12 +119,12 @@ public class WebSocketListenerTest
// Send and receive echo on client.
ByteBuffer payload = BufferUtil.toBuffer("hello world");
- clientEndpoint.session.getRemote().sendBytes(payload);
+ clientEndpoint.session.sendBinary(payload, Callback.NOOP);
ByteBuffer echoMessage = clientEndpoint.binaryMessages.poll(5, TimeUnit.SECONDS);
assertThat(echoMessage, is(payload));
// Close normally.
- clientEndpoint.session.close(StatusCode.NORMAL, "standard close");
+ clientEndpoint.session.close(StatusCode.NORMAL, "standard close", Callback.NOOP);
assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(clientEndpoint.closeCode, is(StatusCode.NORMAL));
assertThat(clientEndpoint.closeReason, is("standard close"));
@@ -136,10 +136,10 @@ public class WebSocketListenerTest
CountDownLatch openLatch = new CountDownLatch(1);
CountDownLatch closeLatch = new CountDownLatch(1);
BlockingQueue textMessages = new BlockingArrayQueue<>();
- WebSocketListener clientEndpoint = new WebSocketListener()
+ Session.Listener clientEndpoint = new Session.Listener.AutoDemanding()
{
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
openLatch.countDown();
}
@@ -162,12 +162,12 @@ public class WebSocketListenerTest
// Send and receive echo on client.
String payload = "hello world";
- session.getRemote().sendString(payload);
+ session.sendText(payload, Callback.NOOP);
String echoMessage = textMessages.poll(5, TimeUnit.SECONDS);
assertThat(echoMessage, is(payload));
// Close normally.
- session.close(StatusCode.NORMAL, "standard close");
+ session.close(StatusCode.NORMAL, "standard close", Callback.NOOP);
assertTrue(closeLatch.await(5, TimeUnit.SECONDS));
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/proxy/WebSocketProxy.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/proxy/WebSocketProxy.java
index f046e34884f..e7b21021f17 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/proxy/WebSocketProxy.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/proxy/WebSocketProxy.java
@@ -13,20 +13,18 @@
package org.eclipse.jetty.websocket.tests.proxy;
+import java.io.IOException;
+import java.io.UncheckedIOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.api.WebSocketConnectionListener;
-import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
-import org.eclipse.jetty.websocket.api.WebSocketPingPongListener;
-import org.eclipse.jetty.websocket.api.exceptions.WebSocketException;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.slf4j.Logger;
@@ -47,7 +45,7 @@ public class WebSocketProxy
this.serverUri = serverUri;
}
- public WebSocketConnectionListener getWebSocketConnectionListener()
+ public Session.Listener getSessionListener()
{
return clientToProxy;
}
@@ -68,7 +66,7 @@ public class WebSocketProxy
}
}
- public class ClientToProxy implements WebSocketPartialListener, WebSocketPingPongListener
+ public class ClientToProxy implements Session.Listener
{
private volatile Session session;
private final CountDownLatch closeLatch = new CountDownLatch(1);
@@ -80,49 +78,47 @@ public class WebSocketProxy
public void fail(Throwable failure)
{
- session.close(StatusCode.SERVER_ERROR, failure.getMessage());
+ String reason = failure.getMessage();
+ session.close(StatusCode.SERVER_ERROR, reason, Callback.NOOP);
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onWebSocketConnect({})", getClass().getSimpleName(), session);
+ LOG.debug("{} onWebSocketOpen({})", getClass().getSimpleName(), session);
- Future connect = null;
try
{
this.session = session;
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.setSubProtocols(session.getUpgradeRequest().getSubProtocols());
upgradeRequest.setExtensions(session.getUpgradeRequest().getExtensions());
- connect = client.connect(proxyToServer, serverUri, upgradeRequest);
-
- //This is blocking as we really want the client to be connected before receiving any messages.
- connect.get();
+ client.connect(proxyToServer, serverUri, upgradeRequest)
+ // Only demand for frames after the connect() is successful.
+ .thenAccept(ignored -> session.demand());
}
- catch (Exception e)
+ catch (IOException x)
{
- if (connect != null)
- connect.cancel(true);
- throw new WebSocketException(e);
+ throw new UncheckedIOException(x);
}
}
@Override
- public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin)
+ public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin, Callback callback)
{
if (LOG.isDebugEnabled())
LOG.debug("{} onWebSocketPartialBinary({}, {})", getClass().getSimpleName(), BufferUtil.toDetailString(payload), fin);
- try
- {
- proxyToServer.getSession().getRemote().sendPartialBytes(payload, fin);
- }
- catch (Exception e)
- {
- throw new WebSocketException(e);
- }
+ Callback.Completable.with(c -> proxyToServer.getSession().sendPartialBinary(payload, fin, c))
+ .thenRun(callback::succeed)
+ .thenRun(session::demand)
+ .exceptionally(x ->
+ {
+ callback.fail(x);
+ fail(x);
+ return null;
+ });
}
@Override
@@ -131,14 +127,7 @@ public class WebSocketProxy
if (LOG.isDebugEnabled())
LOG.debug("{} onWebSocketPartialText({}, {})", getClass().getSimpleName(), StringUtil.truncate(payload, 100), fin);
- try
- {
- proxyToServer.getSession().getRemote().sendPartialString(payload, fin);
- }
- catch (Exception e)
- {
- throw new WebSocketException(e);
- }
+ proxyToServer.getSession().sendPartialText(payload, fin, Callback.from(session::demand, this::fail));
}
@Override
@@ -147,14 +136,7 @@ public class WebSocketProxy
if (LOG.isDebugEnabled())
LOG.debug("{} onWebSocketPing({})", getClass().getSimpleName(), BufferUtil.toDetailString(payload));
- try
- {
- proxyToServer.getSession().getRemote().sendPing(payload);
- }
- catch (Exception e)
- {
- throw new WebSocketException(e);
- }
+ proxyToServer.getSession().sendPing(payload, Callback.from(session::demand, this::fail));
}
@Override
@@ -163,14 +145,7 @@ public class WebSocketProxy
if (LOG.isDebugEnabled())
LOG.debug("{} onWebSocketPong({})", getClass().getSimpleName(), BufferUtil.toDetailString(payload));
- try
- {
- proxyToServer.getSession().getRemote().sendPong(payload);
- }
- catch (Exception e)
- {
- throw new WebSocketException(e);
- }
+ proxyToServer.getSession().sendPong(payload, Callback.from(session::demand, this::fail));
}
@Override
@@ -189,14 +164,14 @@ public class WebSocketProxy
LOG.debug("{} onWebSocketClose({} {})", getClass().getSimpleName(), statusCode, reason);
// Session may be null if connection to the server failed.
- Session session = proxyToServer.getSession();
- if (session != null)
- session.close(statusCode, reason);
+ Session proxyToServerSession = proxyToServer.getSession();
+ if (proxyToServerSession != null)
+ proxyToServerSession.close(statusCode, reason, Callback.NOOP);
closeLatch.countDown();
}
}
- public class ProxyToServer implements WebSocketPartialListener, WebSocketPingPongListener
+ public class ProxyToServer implements Session.Listener
{
private volatile Session session;
private final CountDownLatch closeLatch = new CountDownLatch(1);
@@ -211,32 +186,34 @@ public class WebSocketProxy
// Only ProxyToServer can be failed before it is opened (if ClientToProxy fails before the connect completes).
Session session = this.session;
if (session != null)
- session.close(StatusCode.SERVER_ERROR, failure.getMessage());
+ session.close(StatusCode.SERVER_ERROR, failure.getMessage(), Callback.NOOP);
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onWebSocketConnect({})", getClass().getSimpleName(), session);
+ LOG.debug("{} onWebSocketOpen({})", getClass().getSimpleName(), session);
this.session = session;
+ session.demand();
}
@Override
- public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin)
+ public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin, Callback callback)
{
if (LOG.isDebugEnabled())
LOG.debug("{} onWebSocketPartialBinary({}, {})", getClass().getSimpleName(), BufferUtil.toDetailString(payload), fin);
- try
- {
- clientToProxy.getSession().getRemote().sendPartialBytes(payload, fin);
- }
- catch (Exception e)
- {
- throw new WebSocketException(e);
- }
+ Callback.Completable.with(c -> clientToProxy.getSession().sendPartialBinary(payload, fin, c))
+ .thenRun(callback::succeed)
+ .thenRun(session::demand)
+ .exceptionally(x ->
+ {
+ callback.fail(x);
+ fail(x);
+ return null;
+ });
}
@Override
@@ -245,14 +222,7 @@ public class WebSocketProxy
if (LOG.isDebugEnabled())
LOG.debug("{} onWebSocketPartialText({}, {})", getClass().getSimpleName(), StringUtil.truncate(payload, 100), fin);
- try
- {
- clientToProxy.getSession().getRemote().sendPartialString(payload, fin);
- }
- catch (Exception e)
- {
- throw new WebSocketException(e);
- }
+ clientToProxy.getSession().sendPartialText(payload, fin, Callback.from(session::demand, this::fail));
}
@Override
@@ -261,14 +231,7 @@ public class WebSocketProxy
if (LOG.isDebugEnabled())
LOG.debug("{} onWebSocketPing({})", getClass().getSimpleName(), BufferUtil.toDetailString(payload));
- try
- {
- clientToProxy.getSession().getRemote().sendPing(payload);
- }
- catch (Exception e)
- {
- throw new WebSocketException(e);
- }
+ clientToProxy.getSession().sendPing(payload, Callback.from(session::demand, this::fail));
}
@Override
@@ -277,14 +240,7 @@ public class WebSocketProxy
if (LOG.isDebugEnabled())
LOG.debug("{} onWebSocketPong({})", getClass().getSimpleName(), BufferUtil.toDetailString(payload));
- try
- {
- clientToProxy.getSession().getRemote().sendPong(payload);
- }
- catch (Exception e)
- {
- throw new WebSocketException(e);
- }
+ clientToProxy.getSession().sendPong(payload, Callback.from(session::demand, this::fail));
}
@Override
@@ -302,7 +258,8 @@ public class WebSocketProxy
if (LOG.isDebugEnabled())
LOG.debug("{} onWebSocketClose({} {})", getClass().getSimpleName(), statusCode, reason);
- clientToProxy.getSession().close(statusCode, reason);
+ Session clientToProxySession = clientToProxy.getSession();
+ clientToProxySession.close(statusCode, reason, Callback.NOOP);
closeLatch.countDown();
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/proxy/WebSocketProxyTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/proxy/WebSocketProxyTest.java
index f906b682e25..95ad1df8a93 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/proxy/WebSocketProxyTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/proxy/WebSocketProxyTest.java
@@ -28,6 +28,7 @@ import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.internal.HttpChannelState;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Frame;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
@@ -72,7 +73,7 @@ public class WebSocketProxyTest
context.setHandler(wsHandler);
wsHandler.configure(container ->
{
- container.addMapping("/proxy", (rq, rs, cb) -> webSocketProxy.getWebSocketConnectionListener());
+ container.addMapping("/proxy", (rq, rs, cb) -> webSocketProxy.getSessionListener());
serverSocket = new EchoSocket();
container.addMapping("/echo", (rq, rs, cb) ->
{
@@ -110,15 +111,16 @@ public class WebSocketProxyTest
assertTrue(clientSocket.openLatch.await(5, TimeUnit.SECONDS));
// Test an echo spread across multiple frames.
- clientSocket.session.getRemote().sendPartialString("hell", false);
- clientSocket.session.getRemote().sendPartialString("o w", false);
- clientSocket.session.getRemote().sendPartialString("orld", false);
- clientSocket.session.getRemote().sendPartialString("!", true);
+ Callback.Completable.with(c -> clientSocket.session.sendPartialText("hell", false, c))
+ .compose(c -> clientSocket.session.sendPartialText("o w", false, c))
+ .compose(c -> clientSocket.session.sendPartialText("orld", false, c))
+ .compose(c -> clientSocket.session.sendPartialText("!", true, c))
+ .get();
String response = clientSocket.textMessages.poll(5, TimeUnit.SECONDS);
assertThat(response, is("hello world!"));
// Test we closed successfully on the client side.
- clientSocket.session.close(StatusCode.NORMAL, "test initiated close");
+ clientSocket.session.close(StatusCode.NORMAL, "test initiated close", Callback.NOOP);
assertTrue(clientSocket.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(clientSocket.closeCode, is(StatusCode.NORMAL));
assertThat(clientSocket.closeReason, is("test initiated close"));
@@ -212,7 +214,7 @@ public class WebSocketProxyTest
assertTrue(clientSocket.openLatch.await(5, TimeUnit.SECONDS));
assertTrue(serverSocket.openLatch.await(5, TimeUnit.SECONDS));
- clientSocket.session.getRemote().sendString("hello world!");
+ clientSocket.session.sendText("hello world!", Callback.NOOP);
// Verify expected client close.
assertTrue(clientSocket.closeLatch.await(5, TimeUnit.SECONDS));
@@ -245,7 +247,7 @@ public class WebSocketProxyTest
serverSocket.session.setIdleTimeout(Duration.ZERO);
// Send and receive an echo message.
- clientSocket.session.getRemote().sendString("test echo message");
+ clientSocket.session.sendText("test echo message", Callback.NOOP);
assertThat(clientSocket.textMessages.poll(clientSessionIdleTimeout, TimeUnit.SECONDS), is("test echo message"));
// Wait more than the idleTimeout period, the clientToProxy connection should fail which should fail the proxyToServer.
@@ -273,19 +275,22 @@ public class WebSocketProxyTest
assertTrue(serverSocket.openLatch.await(5, TimeUnit.SECONDS));
// Test unsolicited pong from client.
- clientSocket.session.getRemote().sendPong(BufferUtil.toBuffer("unsolicited pong from client"));
+ ByteBuffer b2 = BufferUtil.toBuffer("unsolicited pong from client");
+ clientSocket.session.sendPong(b2, Callback.NOOP);
assertThat(serverEndpoint.pingMessages.size(), is(0));
assertThat(serverEndpoint.pongMessages.poll(5, TimeUnit.SECONDS), is(BufferUtil.toBuffer("unsolicited pong from client")));
// Test unsolicited pong from server.
- serverEndpoint.session.getRemote().sendPong(BufferUtil.toBuffer("unsolicited pong from server"));
+ ByteBuffer b1 = BufferUtil.toBuffer("unsolicited pong from server");
+ serverEndpoint.session.sendPong(b1, Callback.NOOP);
assertThat(clientSocket.pingMessages.size(), is(0));
assertThat(clientSocket.pongMessages.poll(5, TimeUnit.SECONDS), is(BufferUtil.toBuffer("unsolicited pong from server")));
// Test pings from client.
for (int i = 0; i < 15; i++)
{
- clientSocket.session.getRemote().sendPing(intToStringByteBuffer(i));
+ ByteBuffer b = intToStringByteBuffer(i);
+ clientSocket.session.sendPing(b, Callback.NOOP);
}
for (int i = 0; i < 15; i++)
{
@@ -296,7 +301,8 @@ public class WebSocketProxyTest
// Test pings from server.
for (int i = 0; i < 23; i++)
{
- serverEndpoint.session.getRemote().sendPing(intToStringByteBuffer(i));
+ ByteBuffer b = intToStringByteBuffer(i);
+ serverEndpoint.session.sendPing(b, Callback.NOOP);
}
for (int i = 0; i < 23; i++)
{
@@ -304,7 +310,7 @@ public class WebSocketProxyTest
assertThat(serverEndpoint.pongMessages.poll(5, TimeUnit.SECONDS), is(intToStringByteBuffer(i)));
}
- clientSocket.session.close(StatusCode.NORMAL, "closing from test");
+ clientSocket.session.close(StatusCode.NORMAL, "closing from test", Callback.NOOP);
// Verify expected client close.
assertTrue(clientSocket.closeLatch.await(5, TimeUnit.SECONDS));
@@ -338,19 +344,14 @@ public class WebSocketProxyTest
public BlockingQueue pongMessages = new BlockingArrayQueue<>();
@OnWebSocketFrame
- public void onWebSocketFrame(Frame frame)
+ public void onWebSocketFrame(Frame frame, Callback callback)
{
switch (frame.getOpCode())
{
- case OpCode.PING:
- pingMessages.add(BufferUtil.copy(frame.getPayload()));
- break;
- case OpCode.PONG:
- pongMessages.add(BufferUtil.copy(frame.getPayload()));
- break;
- default:
- break;
+ case OpCode.PING -> pingMessages.add(BufferUtil.copy(frame.getPayload()));
+ case OpCode.PONG -> pongMessages.add(BufferUtil.copy(frame.getPayload()));
}
+ callback.succeed();
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/AbstractCloseEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/AbstractCloseEndpoint.java
index 75316e35db3..1d65952727c 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/AbstractCloseEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/AbstractCloseEndpoint.java
@@ -18,7 +18,6 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.hamcrest.Matcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -27,10 +26,10 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
-public abstract class AbstractCloseEndpoint extends WebSocketAdapter
+public abstract class AbstractCloseEndpoint extends Session.Listener.AbstractAutoDemanding
{
public final Logger log;
- public CountDownLatch openLatch = new CountDownLatch(1);
+ public CountDownLatch connectLatch = new CountDownLatch(1);
public CountDownLatch closeLatch = new CountDownLatch(1);
public String closeReason = null;
public int closeStatusCode = -1;
@@ -42,11 +41,18 @@ public abstract class AbstractCloseEndpoint extends WebSocketAdapter
}
@Override
- public void onWebSocketConnect(Session sess)
+ public void onWebSocketOpen(Session sess)
{
- super.onWebSocketConnect(sess);
- log.debug("onWebSocketConnect({})", sess);
- openLatch.countDown();
+ super.onWebSocketOpen(sess);
+ log.debug("onWebSocketOpen({})", sess);
+ connectLatch.countDown();
+ }
+
+ @Override
+ public void onWebSocketError(Throwable cause)
+ {
+ log.debug("onWebSocketError({})", cause.getClass().getSimpleName());
+ errors.offer(cause);
}
@Override
@@ -58,25 +64,13 @@ public abstract class AbstractCloseEndpoint extends WebSocketAdapter
closeLatch.countDown();
}
- @Override
- public void onWebSocketError(Throwable cause)
- {
- log.debug("onWebSocketError({})", cause.getClass().getSimpleName());
- errors.offer(cause);
- }
-
- public void assertReceivedCloseEvent(int clientTimeoutMs, Matcher statusCodeMatcher, Matcher reasonMatcher)
- throws InterruptedException
+ public void assertReceivedCloseEvent(int clientTimeoutMs, Matcher statusCodeMatcher, Matcher reasonMatcher) throws InterruptedException
{
assertThat("Client Close Event Occurred", closeLatch.await(clientTimeoutMs, TimeUnit.MILLISECONDS), is(true));
assertThat("Client Close Event Status Code", closeStatusCode, statusCodeMatcher);
if (reasonMatcher == null)
- {
assertThat("Client Close Event Reason", closeReason, nullValue());
- }
else
- {
assertThat("Client Close Event Reason", closeReason, reasonMatcher);
- }
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/CloseInOnCloseEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/CloseInOnCloseEndpoint.java
index 4a35dc0bae3..52c9c59afb0 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/CloseInOnCloseEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/CloseInOnCloseEndpoint.java
@@ -13,6 +13,8 @@
package org.eclipse.jetty.websocket.tests.server;
+import org.eclipse.jetty.websocket.api.Callback;
+import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
public class CloseInOnCloseEndpoint extends AbstractCloseEndpoint
@@ -20,7 +22,8 @@ public class CloseInOnCloseEndpoint extends AbstractCloseEndpoint
@Override
public void onWebSocketClose(int statusCode, String reason)
{
- getSession().close(StatusCode.SERVER_ERROR, "this should be a noop");
+ Session session = getSession();
+ session.close(StatusCode.SERVER_ERROR, "this should be a noop", Callback.NOOP);
super.onWebSocketClose(statusCode, reason);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/CloseInOnCloseEndpointNewThread.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/CloseInOnCloseEndpointNewThread.java
index c4323d418d0..5cd8a2980f0 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/CloseInOnCloseEndpointNewThread.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/CloseInOnCloseEndpointNewThread.java
@@ -15,6 +15,8 @@ package org.eclipse.jetty.websocket.tests.server;
import java.util.concurrent.CountDownLatch;
+import org.eclipse.jetty.websocket.api.Callback;
+import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
public class CloseInOnCloseEndpointNewThread extends AbstractCloseEndpoint
@@ -27,7 +29,8 @@ public class CloseInOnCloseEndpointNewThread extends AbstractCloseEndpoint
CountDownLatch complete = new CountDownLatch(1);
new Thread(() ->
{
- getSession().close(StatusCode.SERVER_ERROR, "this should be a noop");
+ Session session = getSession();
+ session.close(StatusCode.SERVER_ERROR, "this should be a noop", Callback.NOOP);
complete.countDown();
}).start();
complete.await();
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ContainerEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ContainerEndpoint.java
index 9f1b750d64e..8ee793c2dd4 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ContainerEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ContainerEndpoint.java
@@ -15,10 +15,10 @@ package org.eclipse.jetty.websocket.tests.server;
import java.util.Collection;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketContainer;
-import org.eclipse.jetty.websocket.api.WriteCallback;
/**
* On Message, return container information
@@ -49,15 +49,15 @@ public class ContainerEndpoint extends AbstractCloseEndpoint
{
ret.append('[').append(idx++).append("] ").append(sess.toString()).append('\n');
}
- session.getRemote().sendString(ret.toString(), WriteCallback.NOOP);
+ session.sendText(ret.toString(), Callback.NOOP);
}
- session.close(StatusCode.NORMAL, "ContainerEndpoint");
+ session.close(StatusCode.NORMAL, "ContainerEndpoint", Callback.NOOP);
}
@Override
- public void onWebSocketConnect(Session sess)
+ public void onWebSocketOpen(Session sess)
{
- log.debug("onWebSocketConnect({})", sess);
+ log.debug("onWebSocketOpen({})", sess);
this.session = sess;
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/DynamicServerConfigurationTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/DynamicServerConfigurationTest.java
index 2cbafe14a3c..032673a76a1 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/DynamicServerConfigurationTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/DynamicServerConfigurationTest.java
@@ -26,8 +26,8 @@ import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.component.LifeCycle;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketContainer;
import org.eclipse.jetty.websocket.api.exceptions.UpgradeException;
@@ -86,7 +86,7 @@ public class DynamicServerConfigurationTest
start(new Handler.Abstract()
{
@Override
- public boolean handle(Request request, Response response, Callback callback) throws Exception
+ public boolean handle(Request request, Response response, org.eclipse.jetty.util.Callback callback) throws Exception
{
String pathInContext = Request.getPathInContext(request);
if ("/config".equals(pathInContext))
@@ -114,7 +114,7 @@ public class DynamicServerConfigurationTest
future = wsClient.connect(clientEndPoint, wsUri);
try (Session session = future.get(5, SECONDS))
{
- session.getRemote().sendString("OK");
+ session.sendText("OK", Callback.NOOP);
String reply = clientEndPoint.textMessages.poll(5, SECONDS);
assertEquals("OK", reply);
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FastCloseEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FastCloseEndpoint.java
index a25f57e7be4..337e93feb37 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FastCloseEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FastCloseEndpoint.java
@@ -13,6 +13,7 @@
package org.eclipse.jetty.websocket.tests.server;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
@@ -22,9 +23,9 @@ import org.eclipse.jetty.websocket.api.StatusCode;
public class FastCloseEndpoint extends AbstractCloseEndpoint
{
@Override
- public void onWebSocketConnect(Session sess)
+ public void onWebSocketOpen(Session sess)
{
- log.debug("onWebSocketConnect({})", sess);
- sess.close(StatusCode.NORMAL, "FastCloseServer");
+ log.debug("onWebSocketOpen({})", sess);
+ sess.close(StatusCode.NORMAL, "FastCloseServer", Callback.NOOP);
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FastFailEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FastFailEndpoint.java
index f95ba16bdaa..3e9776afbc2 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FastFailEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FastFailEndpoint.java
@@ -21,9 +21,9 @@ import org.eclipse.jetty.websocket.api.Session;
public class FastFailEndpoint extends AbstractCloseEndpoint
{
@Override
- public void onWebSocketConnect(Session sess)
+ public void onWebSocketOpen(Session sess)
{
- log.debug("onWebSocketConnect({})", sess);
+ log.debug("onWebSocketOpen({})", sess);
// Test failure due to unhandled exception
// this should trigger a fast-fail closure during open/connect
throw new RuntimeException("Intentional FastFail");
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FrameAnnotationTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FrameAnnotationTest.java
index 30a8a17af80..e606ffb97af 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FrameAnnotationTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FrameAnnotationTest.java
@@ -24,13 +24,13 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Frame;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
@@ -116,10 +116,9 @@ public class FrameAnnotationTest
{
session = futSession.get(5, SECONDS);
- RemoteEndpoint clientRemote = session.getRemote();
- clientRemote.sendPartialString("hello", false);
- clientRemote.sendPartialString(" ", false);
- clientRemote.sendPartialString("world", true);
+ session.sendPartialText("hello", false, Callback.NOOP);
+ session.sendPartialText(" ", false, Callback.NOOP);
+ session.sendPartialText("world", true, Callback.NOOP);
String event = serverEndpoint.frameEvents.poll(5, SECONDS);
assertThat("Event", event, is("FRAME[TEXT,fin=false,payload=hello,len=5]"));
@@ -141,32 +140,33 @@ public class FrameAnnotationTest
public CountDownLatch closeLatch = new CountDownLatch(1);
public LinkedBlockingQueue frameEvents = new LinkedBlockingQueue<>();
- @OnWebSocketClose
- public void onWebSocketClose(int statusCode, String reason)
- {
- closeLatch.countDown();
- }
-
- @OnWebSocketConnect
- public void onWebSocketConnect(Session session)
+ @OnWebSocketOpen
+ public void onWebSocketOpen(Session session)
{
this.session = session;
}
+ @OnWebSocketFrame
+ public void onWebSocketFrame(Frame frame, Callback callback)
+ {
+ frameEvents.offer(String.format("FRAME[%s,fin=%b,payload=%s,len=%d]",
+ OpCode.name(frame.getOpCode()),
+ frame.isFin(),
+ BufferUtil.toUTF8String(frame.getPayload()),
+ frame.getPayloadLength()));
+ callback.succeed();
+ }
+
@OnWebSocketError
public void onWebSocketError(Throwable cause)
{
cause.printStackTrace(System.err);
}
- @OnWebSocketFrame
- public void onWebSocketFrame(Frame frame)
+ @OnWebSocketClose
+ public void onWebSocketClose(int statusCode, String reason)
{
- frameEvents.offer(String.format("FRAME[%s,fin=%b,payload=%s,len=%d]",
- OpCode.name(frame.getOpCode()),
- frame.isFin(),
- BufferUtil.toUTF8String(frame.getPayload()),
- frame.getPayloadLength()));
+ closeLatch.countDown();
}
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FrameListenerTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FrameListenerTest.java
index f124f5a5bd3..682f2c9dcd0 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FrameListenerTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/FrameListenerTest.java
@@ -24,10 +24,9 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Frame;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketFrameListener;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -112,10 +111,9 @@ public class FrameListenerTest
{
session = futSession.get(5, SECONDS);
- RemoteEndpoint clientRemote = session.getRemote();
- clientRemote.sendPartialString("hello", false);
- clientRemote.sendPartialString(" ", false);
- clientRemote.sendPartialString("world", true);
+ session.sendPartialText("hello", false, Callback.NOOP);
+ session.sendPartialText(" ", false, Callback.NOOP);
+ session.sendPartialText("world", true, Callback.NOOP);
String event = serverEndpoint.frameEvents.poll(5, SECONDS);
assertThat("Event", event, is("FRAME[TEXT,fin=false,payload=hello,len=5]"));
@@ -130,22 +128,29 @@ public class FrameListenerTest
}
}
- public static class FrameEndpoint implements WebSocketFrameListener
+ public static class FrameEndpoint implements Session.Listener
{
public Session session;
public CountDownLatch closeLatch = new CountDownLatch(1);
public LinkedBlockingQueue frameEvents = new LinkedBlockingQueue<>();
@Override
- public void onWebSocketClose(int statusCode, String reason)
+ public void onWebSocketOpen(Session session)
{
- closeLatch.countDown();
+ this.session = session;
+ session.demand();
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketFrame(Frame frame, Callback callback)
{
- this.session = session;
+ frameEvents.offer(String.format("FRAME[%s,fin=%b,payload=%s,len=%d]",
+ OpCode.name(frame.getOpCode()),
+ frame.isFin(),
+ BufferUtil.toUTF8String(frame.getPayload()),
+ frame.getPayloadLength()));
+ callback.succeed();
+ session.demand();
}
@Override
@@ -155,13 +160,9 @@ public class FrameListenerTest
}
@Override
- public void onWebSocketFrame(Frame frame)
+ public void onWebSocketClose(int statusCode, String reason)
{
- frameEvents.offer(String.format("FRAME[%s,fin=%b,payload=%s,len=%d]",
- OpCode.name(frame.getOpCode()),
- frame.isFin(),
- BufferUtil.toUTF8String(frame.getPayload()),
- frame.getPayloadLength()));
+ closeLatch.countDown();
}
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/PartialListenerTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/PartialListenerTest.java
index 629be35e894..9fc6d6f589b 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/PartialListenerTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/PartialListenerTest.java
@@ -25,9 +25,8 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -112,10 +111,9 @@ public class PartialListenerTest
{
session = futSession.get(5, SECONDS);
- RemoteEndpoint clientRemote = session.getRemote();
- clientRemote.sendPartialString("hello", false);
- clientRemote.sendPartialString(" ", false);
- clientRemote.sendPartialString("world", true);
+ session.sendPartialText("hello", false, Callback.NOOP);
+ session.sendPartialText(" ", false, Callback.NOOP);
+ session.sendPartialText("world", true, Callback.NOOP);
String event = serverEndpoint.partialEvents.poll(5, SECONDS);
assertThat("Event", event, is("TEXT[payload=hello, fin=false]"));
@@ -144,10 +142,9 @@ public class PartialListenerTest
{
session = futSession.get(5, SECONDS);
- RemoteEndpoint clientRemote = session.getRemote();
- clientRemote.sendPartialBytes(BufferUtil.toBuffer("hello"), false);
- clientRemote.sendPartialBytes(BufferUtil.toBuffer(" "), false);
- clientRemote.sendPartialBytes(BufferUtil.toBuffer("world"), true);
+ session.sendPartialBinary(BufferUtil.toBuffer("hello"), false, Callback.NOOP);
+ session.sendPartialBinary(BufferUtil.toBuffer(" "), false, Callback.NOOP);
+ session.sendPartialBinary(BufferUtil.toBuffer("world"), true, Callback.NOOP);
String event = serverEndpoint.partialEvents.poll(5, SECONDS);
assertThat("Event", event, is("BINARY[payload=<<>>, fin=false]"));
@@ -179,18 +176,17 @@ public class PartialListenerTest
{
session = futSession.get(5, SECONDS);
- RemoteEndpoint clientRemote = session.getRemote();
- clientRemote.sendPartialString("hello", false);
- clientRemote.sendPartialString(" ", false);
- clientRemote.sendPartialString("world", true);
+ session.sendPartialText("hello", false, Callback.NOOP);
+ session.sendPartialText(" ", false, Callback.NOOP);
+ session.sendPartialText("world", true, Callback.NOOP);
- clientRemote.sendPartialBytes(BufferUtil.toBuffer("greetings"), false);
- clientRemote.sendPartialBytes(BufferUtil.toBuffer(" "), false);
- clientRemote.sendPartialBytes(BufferUtil.toBuffer("mars"), true);
+ session.sendPartialBinary(BufferUtil.toBuffer("greetings"), false, Callback.NOOP);
+ session.sendPartialBinary(BufferUtil.toBuffer(" "), false, Callback.NOOP);
+ session.sendPartialBinary(BufferUtil.toBuffer("mars"), true, Callback.NOOP);
- clientRemote.sendPartialString("salutations", false);
- clientRemote.sendPartialString(" ", false);
- clientRemote.sendPartialString("phobos", true);
+ session.sendPartialText("salutations", false, Callback.NOOP);
+ session.sendPartialText(" ", false, Callback.NOOP);
+ session.sendPartialText("phobos", true, Callback.NOOP);
String event;
event = serverEndpoint.partialEvents.poll(5, SECONDS);
@@ -220,22 +216,33 @@ public class PartialListenerTest
}
}
- public static class PartialEndpoint implements WebSocketPartialListener
+ public static class PartialEndpoint implements Session.Listener
{
public Session session;
public CountDownLatch closeLatch = new CountDownLatch(1);
public LinkedBlockingQueue partialEvents = new LinkedBlockingQueue<>();
@Override
- public void onWebSocketClose(int statusCode, String reason)
+ public void onWebSocketOpen(Session session)
{
- closeLatch.countDown();
+ this.session = session;
+ session.demand();
}
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketPartialText(String payload, boolean fin)
{
- this.session = session;
+ partialEvents.offer(String.format("TEXT[payload=%s, fin=%b]", TextUtils.maxStringLength(30, payload), fin));
+ session.demand();
+ }
+
+ @Override
+ public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin, Callback callback)
+ {
+ // our testcases always send bytes limited in the US-ASCII range.
+ partialEvents.offer(String.format("BINARY[payload=<<<%s>>>, fin=%b]", BufferUtil.toUTF8String(payload), fin));
+ callback.succeed();
+ session.demand();
}
@Override
@@ -245,16 +252,9 @@ public class PartialListenerTest
}
@Override
- public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin)
+ public void onWebSocketClose(int statusCode, String reason)
{
- // our testcases always send bytes limited in the US-ASCII range.
- partialEvents.offer(String.format("BINARY[payload=<<<%s>>>, fin=%b]", BufferUtil.toUTF8String(payload), fin));
- }
-
- @Override
- public void onWebSocketPartialText(String payload, boolean fin)
- {
- partialEvents.offer(String.format("TEXT[payload=%s, fin=%b]", TextUtils.maxStringLength(30, payload), fin));
+ closeLatch.countDown();
}
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerCloseTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerCloseTest.java
index e454be331a3..18f093a5ecd 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerCloseTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerCloseTest.java
@@ -22,6 +22,7 @@ import org.eclipse.jetty.logging.StacklessLogging;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.util.WSURI;
@@ -163,7 +164,7 @@ public class ServerCloseTest
AbstractCloseEndpoint serverEndpoint = serverEndpointCreator.pollLastCreated();
serverEndpoint.assertReceivedCloseEvent(5000, is(StatusCode.SERVER_ERROR), containsString("Intentional FastFail"));
- // Validate errors (must be "java.lang.RuntimeException: Intentional Exception from onWebSocketConnect")
+ // Validate errors (must be "java.lang.RuntimeException: Intentional Exception from onWebSocketOpen")
assertThat("socket.onErrors", serverEndpoint.errors.size(), greaterThanOrEqualTo(1));
Throwable cause = serverEndpoint.errors.poll(5, SECONDS);
assertThat("Error type", cause, instanceOf(RuntimeException.class));
@@ -235,7 +236,7 @@ public class ServerCloseTest
{
session = futSession.get(5, SECONDS);
- session.getRemote().sendString("openSessions");
+ session.sendText("openSessions", Callback.NOOP);
String msg = clientEndpoint.messageQueue.poll(5, SECONDS);
@@ -269,8 +270,9 @@ public class ServerCloseTest
// Hard close from the server. Server onClosed() will try to close again which should be a NOOP.
AbstractCloseEndpoint serverEndpoint = serverEndpointCreator.pollLastCreated();
- assertTrue(serverEndpoint.openLatch.await(5, SECONDS));
- serverEndpoint.getSession().close(StatusCode.SHUTDOWN, "SHUTDOWN hard close");
+ assertTrue(serverEndpoint.connectLatch.await(5, SECONDS));
+ Session session = serverEndpoint.getSession();
+ session.close(StatusCode.SHUTDOWN, "SHUTDOWN hard close", Callback.NOOP);
// Verify that client got close
clientEndpoint.assertReceivedCloseEvent(5000, is(StatusCode.SHUTDOWN), containsString("SHUTDOWN hard close"));
@@ -293,8 +295,9 @@ public class ServerCloseTest
// Hard close from the server. Server onClosed() will try to close again which should be a NOOP.
AbstractCloseEndpoint serverEndpoint = serverEndpointCreator.pollLastCreated();
- assertTrue(serverEndpoint.openLatch.await(5, SECONDS));
- serverEndpoint.getSession().close(StatusCode.SHUTDOWN, "SHUTDOWN hard close");
+ assertTrue(serverEndpoint.connectLatch.await(5, SECONDS));
+ Session session = serverEndpoint.getSession();
+ session.close(StatusCode.SHUTDOWN, "SHUTDOWN hard close", Callback.NOOP);
// Verify that client got close
clientEndpoint.assertReceivedCloseEvent(5000, is(StatusCode.SHUTDOWN), containsString("SHUTDOWN hard close"));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerConfigTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerConfigTest.java
index 165ae27bba5..5fb63b6acc7 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerConfigTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerConfigTest.java
@@ -14,6 +14,7 @@
package org.eclipse.jetty.websocket.tests.server;
import java.net.URI;
+import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
@@ -28,7 +29,7 @@ import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.PathMappingsHandler;
import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.websocket.api.BatchMode;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@@ -64,7 +65,6 @@ public class ServerConfigTest
private static final int MAX_MESSAGE_SIZE = 20;
private static final int IDLE_TIMEOUT = 500;
- private final EventSocket annotatedEndpoint = new AnnotatedConfigEndpoint();
private final EventSocket sessionConfigEndpoint = new SessionConfigEndpoint();
private final EventSocket standardEndpoint = new EventSocket();
@@ -73,7 +73,6 @@ public class ServerConfigTest
return switch (path)
{
case "servletConfig", "containerConfig" -> standardEndpoint;
- case "annotatedConfig" -> annotatedEndpoint;
case "sessionConfig" -> sessionConfigEndpoint;
default -> throw new IllegalStateException();
};
@@ -81,12 +80,7 @@ public class ServerConfigTest
public static Stream data()
{
- return Stream.of("servletConfig", "annotatedConfig", "containerConfig", "sessionConfig").map(Arguments::of);
- }
-
- @WebSocket(idleTimeout = IDLE_TIMEOUT, maxTextMessageSize = MAX_MESSAGE_SIZE, maxBinaryMessageSize = MAX_MESSAGE_SIZE, inputBufferSize = INPUT_BUFFER_SIZE, batchMode = BatchMode.ON)
- public static class AnnotatedConfigEndpoint extends EventSocket
- {
+ return Stream.of("servletConfig", "containerConfig", "sessionConfig").map(Arguments::of);
}
@WebSocket
@@ -119,16 +113,6 @@ public class ServerConfigTest
}
}
- public static class AnnotatedConfigWebSocketUpgradeHandler
- {
- public static WebSocketUpgradeHandler from(Server server, ContextHandler context, Object wsEndPoint)
- {
- return WebSocketUpgradeHandler.from(server, context)
- .configure(container ->
- container.addMapping("/", (rq, rs, cb) -> wsEndPoint));
- }
- }
-
public static class SessionConfigWebSocketUpgradeHandler
{
public static WebSocketUpgradeHandler from(Server server, ContextHandler context, Object wsEndPoint)
@@ -178,7 +162,6 @@ public class ServerConfigTest
PathMappingsHandler pathsHandler = new PathMappingsHandler();
context.setHandler(pathsHandler);
pathsHandler.addMapping(new ServletPathSpec("/servletConfig"), ConfigWebSocketUpgradeHandler.from(server, context, standardEndpoint));
- pathsHandler.addMapping(new ServletPathSpec("/annotatedConfig"), AnnotatedConfigWebSocketUpgradeHandler.from(server, context, annotatedEndpoint));
pathsHandler.addMapping(new ServletPathSpec("/sessionConfig"), SessionConfigWebSocketUpgradeHandler.from(server, context, sessionConfigEndpoint));
pathsHandler.addMapping(new ServletPathSpec("/"), WebSocketUpgradeHandler.from(server, context)
.configure(container ->
@@ -241,7 +224,8 @@ public class ServerConfigTest
CompletableFuture connect = client.connect(clientEndpoint, uri);
connect.get(5, TimeUnit.SECONDS);
- clientEndpoint.session.getRemote().sendBytes(BufferUtil.toBuffer(MESSAGE));
+ ByteBuffer buffer = BufferUtil.toBuffer(MESSAGE);
+ clientEndpoint.session.sendBinary(buffer, Callback.NOOP);
assertTrue(serverEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(serverEndpoint.error, instanceOf(MessageTooLargeException.class));
@@ -262,7 +246,7 @@ public class ServerConfigTest
CompletableFuture connect = client.connect(clientEndpoint, uri);
connect.get(5, TimeUnit.SECONDS);
- clientEndpoint.session.getRemote().sendString("hello world");
+ clientEndpoint.session.sendText("hello world", Callback.NOOP);
String msg = serverEndpoint.textMessages.poll(500, TimeUnit.MILLISECONDS);
assertThat(msg, is("hello world"));
Thread.sleep(IDLE_TIMEOUT + 500);
@@ -286,7 +270,7 @@ public class ServerConfigTest
CompletableFuture connect = client.connect(clientEndpoint, uri);
connect.get(5, TimeUnit.SECONDS);
- clientEndpoint.session.getRemote().sendString(MESSAGE);
+ clientEndpoint.session.sendText(MESSAGE, Callback.NOOP);
assertTrue(serverEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(serverEndpoint.error, instanceOf(MessageTooLargeException.class));
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerEndpoint.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerEndpoint.java
index b60bfcbafd7..47bda829ded 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerEndpoint.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerEndpoint.java
@@ -13,11 +13,11 @@
package org.eclipse.jetty.websocket.tests.server;
-import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@@ -44,7 +44,7 @@ public class SlowServerEndpoint
{
try
{
- session.getRemote().sendString("Hello/" + i + "/");
+ session.sendText("Hello/" + i + "/", Callback.NOOP);
// fake some slowness
TimeUnit.MILLISECONDS.sleep(random.nextInt(2000));
}
@@ -58,14 +58,7 @@ public class SlowServerEndpoint
else
{
// echo message.
- try
- {
- session.getRemote().sendString(msg);
- }
- catch (IOException ignore)
- {
- LOG.trace("IGNORED", ignore);
- }
+ session.sendText(msg, Callback.NOOP);
}
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerTest.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerTest.java
index 1df42ff23de..082f9a3b80e 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerTest.java
@@ -21,6 +21,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -96,7 +97,7 @@ public class SlowServerTest
int messageCount = 10;
- session.getRemote().sendString("send-slow|" + messageCount);
+ session.sendText("send-slow|" + messageCount, Callback.NOOP);
// Verify receive
LinkedBlockingQueue responses = clientEndpoint.messageQueue;
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/util/FutureWriteCallback.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/util/FutureCallback.java
similarity index 73%
rename from jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/util/FutureWriteCallback.java
rename to jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/util/FutureCallback.java
index 670ba0d98c3..27fbe4f5cde 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/util/FutureWriteCallback.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/util/FutureCallback.java
@@ -15,20 +15,19 @@ package org.eclipse.jetty.websocket.tests.util;
import java.util.concurrent.Future;
-import org.eclipse.jetty.util.FutureCallback;
-import org.eclipse.jetty.websocket.api.WriteCallback;
+import org.eclipse.jetty.websocket.api.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Allows events to a {@link WriteCallback} to drive a {@link Future} for the user.
+ * Allows events to a {@link Callback} to drive a {@link Future} for the user.
*/
-public class FutureWriteCallback extends FutureCallback implements WriteCallback
+public class FutureCallback extends org.eclipse.jetty.util.FutureCallback implements Callback
{
- private static final Logger LOG = LoggerFactory.getLogger(FutureWriteCallback.class);
+ private static final Logger LOG = LoggerFactory.getLogger(FutureCallback.class);
@Override
- public void writeFailed(Throwable cause)
+ public void fail(Throwable cause)
{
if (LOG.isDebugEnabled())
LOG.debug(".writeFailed", cause);
@@ -36,7 +35,7 @@ public class FutureWriteCallback extends FutureCallback implements WriteCallback
}
@Override
- public void writeSuccess()
+ public void succeed()
{
if (LOG.isDebugEnabled())
LOG.debug(".writeSuccess");
diff --git a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/java/org/eclipse/jetty/ee10/demos/WebSocketServer.java b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/java/org/eclipse/jetty/ee10/demos/WebSocketServer.java
index 30a1aec38ca..f0d5e429520 100644
--- a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/java/org/eclipse/jetty/ee10/demos/WebSocketServer.java
+++ b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/java/org/eclipse/jetty/ee10/demos/WebSocketServer.java
@@ -18,8 +18,8 @@ import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServlet;
import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServletFactory;
import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WriteCallback;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@@ -39,7 +39,7 @@ public class WebSocketServer
@OnWebSocketMessage
public void onMessage(Session session, String message)
{
- session.getRemote().sendString(message, WriteCallback.NOOP);
+ session.sendText(message, Callback.NOOP);
}
}
diff --git a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/WebSocketServerTest.java b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/WebSocketServerTest.java
index 3749a491961..c15db6da22f 100644
--- a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/WebSocketServerTest.java
+++ b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/WebSocketServerTest.java
@@ -20,6 +20,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.component.LifeCycle;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
@@ -68,7 +69,7 @@ public class WebSocketServerTest
Future sessionFut = webSocketClient.connect(clientEndpoint, wsUri);
Session session = sessionFut.get(2, SECONDS);
- session.getRemote().sendString("Hello World");
+ session.sendText("Hello World", Callback.NOOP);
String response = clientEndpoint.messages.poll(2, SECONDS);
assertThat("Response", response, is("Hello World"));
diff --git a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-jetty-webapp/src/main/java/org/example/WebSocketChatServlet.java b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-jetty-webapp/src/main/java/org/example/WebSocketChatServlet.java
index 41436dcf687..b5b43620c6b 100644
--- a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-jetty-webapp/src/main/java/org/example/WebSocketChatServlet.java
+++ b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-jetty-webapp/src/main/java/org/example/WebSocketChatServlet.java
@@ -26,11 +26,10 @@ import org.eclipse.jetty.ee10.websocket.server.JettyServerUpgradeResponse;
import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketCreator;
import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServlet;
import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServletFactory;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@SuppressWarnings("serial")
@@ -71,13 +70,11 @@ public class WebSocketChatServlet extends JettyWebSocketServlet implements Jetty
public class ChatWebSocket
{
volatile Session session;
- volatile RemoteEndpoint remote;
- @OnWebSocketConnect
- public void onOpen(Session sess)
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
- this.session = sess;
- this.remote = sess.getRemote();
+ this.session = session;
members.add(this);
}
@@ -103,7 +100,7 @@ public class WebSocketChatServlet extends JettyWebSocketServlet implements Jetty
}
// Async write the message back.
- member.remote.sendString(data, null);
+ member.session.sendText(data, null);
}
}
diff --git a/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/java/org/eclipse/jetty/ee10/osgi/test/SimpleEchoSocket.java b/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/java/org/eclipse/jetty/ee10/osgi/test/SimpleEchoSocket.java
index a230af84381..5090a98dcb0 100644
--- a/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/java/org/eclipse/jetty/ee10/osgi/test/SimpleEchoSocket.java
+++ b/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/java/org/eclipse/jetty/ee10/osgi/test/SimpleEchoSocket.java
@@ -16,22 +16,21 @@ package org.eclipse.jetty.ee10.osgi.test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
/**
* Basic Echo Client Socket
*/
-@WebSocket(maxTextMessageSize = 64 * 1024)
+@WebSocket
public class SimpleEchoSocket
{
private final CountDownLatch closeLatch;
- @SuppressWarnings("unused")
- private Session session;
public SimpleEchoSocket()
{
@@ -46,18 +45,17 @@ public class SimpleEchoSocket
@OnWebSocketClose
public void onClose(int statusCode, String reason)
{
- this.session = null;
this.closeLatch.countDown(); // trigger latch
}
- @OnWebSocketConnect
- public void onConnect(Session session)
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
- this.session = session;
+ session.setMaxTextMessageSize(64 * 1024);
try
{
- session.getRemote().sendString("Foo");
- session.close(StatusCode.NORMAL, "I'm done");
+ session.sendText("Foo", Callback.NOOP);
+ session.close(StatusCode.NORMAL, "I'm done", Callback.NOOP);
}
catch (Throwable t)
{
diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java
index 86127afa9d4..a6f0f6c0816 100644
--- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java
+++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java
@@ -16,6 +16,7 @@ package org.eclipse.jetty.ee10.servlet;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.InvalidPathException;
import java.time.Duration;
@@ -188,9 +189,9 @@ public class DefaultServlet extends HttpServlet
{
private static final Logger LOG = LoggerFactory.getLogger(DefaultServlet.class);
+ private ServletContextHandler _contextHandler;
private ServletResourceService _resourceService;
private WelcomeServletMode _welcomeServletMode;
- private ResourceFactory.Closeable _resourceFactory;
private Resource _baseResource;
private boolean _isPathInfoOnly;
@@ -202,19 +203,17 @@ public class DefaultServlet extends HttpServlet
@Override
public void init() throws ServletException
{
- ServletContextHandler servletContextHandler = initContextHandler(getServletContext());
- _resourceService = new ServletResourceService(servletContextHandler);
+ _contextHandler = initContextHandler(getServletContext());
+ _resourceService = new ServletResourceService(_contextHandler);
_resourceService.setWelcomeFactory(_resourceService);
-
- _baseResource = servletContextHandler.getBaseResource();
- _resourceFactory = ResourceFactory.closeable();
+ _baseResource = _contextHandler.getBaseResource();
String rb = getInitParameter("baseResource", "resourceBase");
if (rb != null)
{
try
{
- _baseResource = _resourceFactory.newResource(rb);
+ _baseResource = Objects.requireNonNull(_contextHandler.newResource(rb));
}
catch (Exception e)
{
@@ -230,17 +229,19 @@ public class DefaultServlet extends HttpServlet
HttpContent.Factory contentFactory = (HttpContent.Factory)getServletContext().getAttribute(HttpContent.Factory.class.getName());
if (contentFactory == null)
{
- MimeTypes mimeTypes = servletContextHandler.getMimeTypes();
- contentFactory = new ResourceHttpContentFactory(ResourceFactory.of(_baseResource), mimeTypes);
+ MimeTypes mimeTypes = _contextHandler.getMimeTypes();
+ ResourceFactory resourceFactory = _baseResource != null ? ResourceFactory.of(_baseResource) : this::getResource;
+ contentFactory = new ResourceHttpContentFactory(resourceFactory, mimeTypes);
// Use the servers default stylesheet unless there is one explicitly set by an init param.
- Resource styleSheet = servletContextHandler.getServer().getDefaultStyleSheet();
+ Resource styleSheet = _contextHandler.getServer().getDefaultStyleSheet();
String stylesheetParam = getInitParameter("stylesheet");
if (stylesheetParam != null)
{
try
{
- Resource s = _resourceFactory.newResource(stylesheetParam);
+ HttpContent styleSheetContent = contentFactory.getContent(stylesheetParam);
+ Resource s = styleSheetContent == null ? null : styleSheetContent.getResource();
if (Resources.isReadableFile(s))
styleSheet = s;
else
@@ -267,7 +268,7 @@ public class DefaultServlet extends HttpServlet
long cacheValidationTime = getInitParameter("cacheValidationTime") != null ? Long.parseLong(getInitParameter("cacheValidationTime")) : -2;
if (maxCachedFiles != -2 || maxCacheSize != -2 || maxCachedFileSize != -2 || cacheValidationTime != -2)
{
- ByteBufferPool bufferPool = getByteBufferPool(servletContextHandler);
+ ByteBufferPool bufferPool = getByteBufferPool(_contextHandler);
ValidatingCachingHttpContentFactory cached = new ValidatingCachingHttpContentFactory(contentFactory,
(cacheValidationTime > -2) ? cacheValidationTime : Duration.ofSeconds(1).toMillis(), bufferPool);
contentFactory = cached;
@@ -281,8 +282,8 @@ public class DefaultServlet extends HttpServlet
}
_resourceService.setHttpContentFactory(contentFactory);
- if (servletContextHandler.getWelcomeFiles() == null)
- servletContextHandler.setWelcomeFiles(new String[]{"index.html", "index.jsp"});
+ if (_contextHandler.getWelcomeFiles() == null)
+ _contextHandler.setWelcomeFiles(new String[]{"index.html", "index.jsp"});
_resourceService.setAcceptRanges(getInitBoolean("acceptRanges", _resourceService.isAcceptRanges()));
_resourceService.setDirAllowed(getInitBoolean("dirAllowed", _resourceService.isDirAllowed()));
@@ -336,7 +337,6 @@ public class DefaultServlet extends HttpServlet
if (LOG.isDebugEnabled())
{
LOG.debug(" .baseResource = {}", _baseResource);
- LOG.debug(" .resourceFactory = {}", _resourceFactory);
LOG.debug(" .resourceService = {}", _resourceService);
LOG.debug(" .isPathInfoOnly = {}", _isPathInfoOnly);
LOG.debug(" .welcomeServletMode = {}", _welcomeServletMode);
@@ -372,13 +372,6 @@ public class DefaultServlet extends HttpServlet
return null;
}
- @Override
- public void destroy()
- {
- super.destroy();
- IO.close(_resourceFactory);
- }
-
private List parsePrecompressedFormats(String precompressed, Boolean gzip, List dft)
{
if (precompressed == null && gzip == null)
@@ -554,6 +547,23 @@ public class DefaultServlet extends HttpServlet
doGet(req, resp);
}
+ private Resource getResource(URI uri)
+ {
+ String uriPath = uri.getRawPath();
+ Resource result = null;
+ try
+ {
+ result = _contextHandler.getResource(uriPath);
+ }
+ catch (IOException x)
+ {
+ LOG.trace("IGNORED", x);
+ }
+ if (LOG.isDebugEnabled())
+ LOG.debug("Resource {}={}", uriPath, result);
+ return result;
+ }
+
private static class ServletCoreRequest extends Request.Wrapper
{
// TODO fully implement this class and move it to the top level
diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-cdi/src/test/java/org/eclipse/jetty/ee10/cdi/tests/websocket/JettyWebSocketCdiTest.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-cdi/src/test/java/org/eclipse/jetty/ee10/cdi/tests/websocket/JettyWebSocketCdiTest.java
index ca24b2e423c..a283cf7ad06 100644
--- a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-cdi/src/test/java/org/eclipse/jetty/ee10/cdi/tests/websocket/JettyWebSocketCdiTest.java
+++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-cdi/src/test/java/org/eclipse/jetty/ee10/cdi/tests/websocket/JettyWebSocketCdiTest.java
@@ -27,11 +27,12 @@ import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletConta
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.BlockingArrayQueue;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.junit.jupiter.api.AfterEach;
@@ -112,7 +113,7 @@ public class JettyWebSocketCdiTest
TestClientEndpoint clientEndpoint = new TestClientEndpoint();
URI uri = URI.create("ws://localhost:" + _connector.getLocalPort() + "/echo");
Session session = _client.connect(clientEndpoint, uri).get(5, TimeUnit.SECONDS);
- session.getRemote().sendString("hello world");
+ session.sendText("hello world", Callback.NOOP);
assertThat(clientEndpoint._textMessages.poll(5, TimeUnit.SECONDS), is("hello world"));
session.close();
assertTrue(clientEndpoint._closeLatch.await(5, TimeUnit.SECONDS));
@@ -126,7 +127,7 @@ public class JettyWebSocketCdiTest
private Session session;
- @OnWebSocketConnect
+ @OnWebSocketOpen
public void onOpen(Session session)
{
logger.info("onOpen() session:" + session);
@@ -136,7 +137,7 @@ public class JettyWebSocketCdiTest
@OnWebSocketMessage
public void onMessage(String message) throws IOException
{
- this.session.getRemote().sendString(message);
+ this.session.sendText(message, Callback.NOOP);
}
@OnWebSocketError
diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/websocket/JettySimpleEchoSocket.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/websocket/JettySimpleEchoSocket.java
index f2aa9387a8f..7639a677e14 100644
--- a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/websocket/JettySimpleEchoSocket.java
+++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/websocket/JettySimpleEchoSocket.java
@@ -16,11 +16,12 @@ package org.eclipse.jetty.ee10.test.websocket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,7 +29,7 @@ import org.slf4j.LoggerFactory;
/**
* Basic Echo Client Socket
*/
-@WebSocket(maxTextMessageSize = 64 * 1024)
+@WebSocket
public class JettySimpleEchoSocket
{
private static final Logger LOG = LoggerFactory.getLogger(JettySimpleEchoSocket.class);
@@ -54,15 +55,16 @@ public class JettySimpleEchoSocket
this.closeLatch.countDown(); // trigger latch
}
- @OnWebSocketConnect
- public void onConnect(Session session)
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
- LOG.debug("Got connect: {}", session);
+ LOG.debug("Open: {}", session);
this.session = session;
+ session.setMaxTextMessageSize(64 * 1024);
try
{
- session.getRemote().sendString("Foo");
- session.close(StatusCode.NORMAL, "I'm done");
+ session.sendText("Foo", Callback.NOOP);
+ session.close(StatusCode.NORMAL, "I'm done", Callback.NOOP);
}
catch (Throwable t)
{
diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-websocket-client-provided-webapp/src/main/java/org/eclipse/jetty/ee10/tests/webapp/websocket/WebSocketClientServlet.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-websocket-client-provided-webapp/src/main/java/org/eclipse/jetty/ee10/tests/webapp/websocket/WebSocketClientServlet.java
index 8fc6f60ce11..c1422eb4879 100644
--- a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-websocket-client-provided-webapp/src/main/java/org/eclipse/jetty/ee10/tests/webapp/websocket/WebSocketClientServlet.java
+++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-websocket-client-provided-webapp/src/main/java/org/eclipse/jetty/ee10/tests/webapp/websocket/WebSocketClientServlet.java
@@ -25,10 +25,11 @@ import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -78,7 +79,7 @@ public class WebSocketClientServlet extends HttpServlet
ClientSocket clientSocket = new ClientSocket();
URI wsUri = WSURI.toWebsocket(req.getRequestURL()).resolve("echo");
client.connect(clientSocket, wsUri).get(5, TimeUnit.SECONDS);
- clientSocket.session.getRemote().sendString("test message");
+ clientSocket.session.sendText("test message", Callback.NOOP);
String response = clientSocket.textMessages.poll(5, TimeUnit.SECONDS);
clientSocket.session.close();
clientSocket.closeLatch.await(5, TimeUnit.SECONDS);
@@ -106,7 +107,7 @@ public class WebSocketClientServlet extends HttpServlet
public CountDownLatch closeLatch = new CountDownLatch(1);
public ArrayBlockingQueue textMessages = new ArrayBlockingQueue<>(10);
- @OnWebSocketConnect
+ @OnWebSocketOpen
public void onOpen(Session session)
{
this.session = session;
diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-websocket-client-webapp/src/main/java/org/eclipse/jetty/ee10/tests/webapp/websocket/WebSocketClientServlet.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-websocket-client-webapp/src/main/java/org/eclipse/jetty/ee10/tests/webapp/websocket/WebSocketClientServlet.java
index ab9d3a42006..2296e524372 100644
--- a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-websocket-client-webapp/src/main/java/org/eclipse/jetty/ee10/tests/webapp/websocket/WebSocketClientServlet.java
+++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-websocket-client-webapp/src/main/java/org/eclipse/jetty/ee10/tests/webapp/websocket/WebSocketClientServlet.java
@@ -28,10 +28,11 @@ import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -86,7 +87,7 @@ public class WebSocketClientServlet extends HttpServlet
ClientSocket clientSocket = new ClientSocket();
URI wsUri = WSURI.toWebsocket(req.getRequestURL()).resolve("echo");
client.connect(clientSocket, wsUri).get(5, TimeUnit.SECONDS);
- clientSocket.session.getRemote().sendString("test message");
+ clientSocket.session.sendText("test message", Callback.NOOP);
String response = clientSocket.textMessages.poll(5, TimeUnit.SECONDS);
clientSocket.session.close();
clientSocket.closeLatch.await(5, TimeUnit.SECONDS);
@@ -110,7 +111,7 @@ public class WebSocketClientServlet extends HttpServlet
public CountDownLatch closeLatch = new CountDownLatch(1);
public ArrayBlockingQueue textMessages = new ArrayBlockingQueue<>(10);
- @OnWebSocketConnect
+ @OnWebSocketOpen
public void onOpen(Session session)
{
this.session = session;
diff --git a/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/HugeResourceTest.java b/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/HugeResourceTest.java
index 6f894aefc22..fda0e4dd151 100644
--- a/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/HugeResourceTest.java
+++ b/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/HugeResourceTest.java
@@ -509,7 +509,7 @@ public class HugeResourceTest
Thread.sleep(100);
stalled.set(false);
demand.get().run();
- assertTrue(complete.await(30, TimeUnit.SECONDS));
+ assertTrue(complete.await(90, TimeUnit.SECONDS));
Response response = responseRef.get();
assertThat("HTTP Response Code", response.getStatus(), is(200));
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-client/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/client/JakartaWebSocketClientContainer.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-client/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/client/JakartaWebSocketClientContainer.java
index 5e17f9311a9..e9773e4a915 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-client/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/client/JakartaWebSocketClientContainer.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-client/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/client/JakartaWebSocketClientContainer.java
@@ -334,7 +334,7 @@ public class JakartaWebSocketClientContainer extends JakartaWebSocketContainer i
{
container.addManaged(this);
if (LOG.isDebugEnabled())
- LOG.debug("{} registered for Context shutdown to {}", this, container);
+ LOG.debug("{} registered for WebApp shutdown to {}", this, container);
return;
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/pom.xml b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/pom.xml
index 0acf34f1d0d..08990ec01a1 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/pom.xml
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/pom.xml
@@ -56,10 +56,16 @@
org.slf4j
slf4j-api
+
org.eclipse.jetty
jetty-slf4j-impl
test
+
+ org.awaitility
+ awaitility
+ test
+
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandler.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
index 6893eb98b28..8527b3a6951 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
@@ -322,12 +322,6 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
}
}
- @Override
- public boolean isAutoDemanding()
- {
- return false;
- }
-
public Set getMessageHandlers()
{
return messageHandlerMap.values().stream()
@@ -600,6 +594,11 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
{
callback.succeeded();
coreSession.demand(1);
+ }, x ->
+ {
+ // Ignore failures, as we might be OSHUT but receive a PING.
+ callback.succeeded();
+ coreSession.demand(1);
}), false);
}
@@ -616,14 +615,19 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
// Use JSR356 PongMessage interface
JakartaWebSocketPongMessage pongMessage = new JakartaWebSocketPongMessage(payload);
pongHandle.invoke(pongMessage);
+ callback.succeeded();
+ coreSession.demand(1);
}
catch (Throwable cause)
{
- throw new WebSocketException(endpointInstance.getClass().getSimpleName() + " PONG method error: " + cause.getMessage(), cause);
+ callback.failed(new WebSocketException(endpointInstance.getClass().getSimpleName() + " PONG method error: " + cause.getMessage(), cause));
}
}
- callback.succeeded();
- coreSession.demand(1);
+ else
+ {
+ callback.succeeded();
+ coreSession.demand(1);
+ }
}
public void onText(Frame frame, Callback callback)
@@ -646,14 +650,9 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
{
switch (dataType)
{
- case OpCode.TEXT:
- onText(frame, callback);
- break;
- case OpCode.BINARY:
- onBinary(frame, callback);
- break;
- default:
- throw new ProtocolException("Unable to process continuation during dataType " + dataType);
+ case OpCode.TEXT -> onText(frame, callback);
+ case OpCode.BINARY -> onBinary(frame, callback);
+ default -> callback.failed(new ProtocolException("Unable to process continuation during dataType " + dataType));
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
index 3d0174cb590..dd90ab38a13 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
@@ -197,8 +197,8 @@ public abstract class JakartaWebSocketFrameHandlerFactory
else
{
MethodHandle ctorHandle = lookup.findConstructor(msgMetadata.getSinkClass(),
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class));
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle());
+ MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, boolean.class));
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle(), true);
}
}
catch (NoSuchMethodException e)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
index aa18950a2f0..d3715baf894 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
@@ -45,7 +45,7 @@ public class DecodedBinaryMessageSink extends AbstractDecodedMessageSink.Basi
MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
.findVirtual(DecodedBinaryMessageSink.class, "onWholeMessage", MethodType.methodType(void.class, ByteBuffer.class))
.bindTo(this);
- return new ByteBufferMessageSink(coreSession, methodHandle);
+ return new ByteBufferMessageSink(coreSession, methodHandle, true);
}
public void onWholeMessage(ByteBuffer wholeMessage)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
index 5de362c1e96..6e7b34c3ce0 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
@@ -42,7 +42,7 @@ public class DecodedBinaryStreamMessageSink extends AbstractDecodedMessageSin
MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
.findVirtual(DecodedBinaryStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, InputStream.class))
.bindTo(this);
- return new InputStreamMessageSink(coreSession, methodHandle);
+ return new InputStreamMessageSink(coreSession, methodHandle, true);
}
public void onStreamStart(InputStream stream)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSink.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSink.java
index 1f480a0f856..6b9f98b6b13 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSink.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSink.java
@@ -44,7 +44,7 @@ public class DecodedTextMessageSink extends AbstractDecodedMessageSink.Basic<
MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
.findVirtual(getClass(), "onMessage", MethodType.methodType(void.class, String.class))
.bindTo(this);
- return new StringMessageSink(coreSession, methodHandle);
+ return new StringMessageSink(coreSession, methodHandle, true);
}
public void onMessage(String wholeMessage)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
index 36c901988ee..59bed6e8b85 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
@@ -42,7 +42,7 @@ public class DecodedTextStreamMessageSink extends AbstractDecodedMessageSink.
MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
.findVirtual(DecodedTextStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, Reader.class))
.bindTo(this);
- return new ReaderMessageSink(coreSession, methodHandle);
+ return new ReaderMessageSink(coreSession, methodHandle, true);
}
public void onStreamStart(Reader reader)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/AbstractSessionTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/AbstractSessionTest.java
index f8a26ac940a..d759362e836 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/AbstractSessionTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/AbstractSessionTest.java
@@ -22,20 +22,20 @@ import jakarta.websocket.Session;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.assertTrue;
public abstract class AbstractSessionTest
{
- protected static JakartaWebSocketSession session;
- protected static JakartaWebSocketContainer container = new DummyContainer();
- protected static WebSocketComponents components = new WebSocketComponents();
- protected static TestCoreSession coreSession = new TestCoreSession();
+ protected JakartaWebSocketContainer container = new DummyContainer();
+ protected WebSocketComponents components = new WebSocketComponents();
+ protected TestCoreSession coreSession = new TestCoreSession(components);
+ protected JakartaWebSocketSession session;
- @BeforeAll
- public static void initSession() throws Exception
+ @BeforeEach
+ public void initSession() throws Exception
{
container.start();
components.start();
@@ -46,8 +46,8 @@ public abstract class AbstractSessionTest
.newDefaultEndpointConfig(websocketPojo.getClass()));
}
- @AfterAll
- public static void stopContainer() throws Exception
+ @AfterEach
+ public void stopContainer() throws Exception
{
components.stop();
container.stop();
@@ -56,6 +56,12 @@ public abstract class AbstractSessionTest
public static class TestCoreSession extends CoreSession.Empty
{
private final Semaphore demand = new Semaphore(0);
+ private final WebSocketComponents components;
+
+ public TestCoreSession(WebSocketComponents components)
+ {
+ this.components = components;
+ }
@Override
public WebSocketComponents getWebSocketComponents()
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
index f399c870f60..4e21e76d317 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
@@ -26,7 +26,6 @@ import java.util.function.Consumer;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
import jakarta.websocket.EndpointConfig;
-import org.eclipse.jetty.ee10.websocket.jakarta.common.AbstractSessionTest;
import org.eclipse.jetty.ee10.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
@@ -47,7 +46,7 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(AbstractSessionTest.session.getCoreSession(), copyHandle, decoders);
+ DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(session.getCoreSession(), copyHandle, decoders);
FutureCallback finCallback = new FutureCallback();
ByteBuffer data = ByteBuffer.allocate(16);
@@ -70,7 +69,7 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(AbstractSessionTest.session.getCoreSession(), copyHandle, decoders);
+ DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(session.getCoreSession(), copyHandle, decoders);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
index 9a20624855f..b91f0e28702 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
@@ -25,7 +25,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
-import org.eclipse.jetty.ee10.websocket.jakarta.common.AbstractSessionTest;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.FutureCallback;
@@ -36,6 +35,7 @@ import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.awaitility.Awaitility.await;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -46,7 +46,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle);
+ InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback finCallback = new FutureCallback();
ByteBuffer data = BufferUtil.toBuffer("Hello World", UTF_8);
@@ -64,7 +64,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle);
+ InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback fin1Callback = new FutureCallback();
ByteBuffer data1 = BufferUtil.toBuffer("Hello World", UTF_8);
@@ -77,6 +77,8 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
assertThat("Writer.contents", byteStream.toString(UTF_8), is("Hello World"));
assertThat("FinCallback.done", fin1Callback.isDone(), is(true));
+ await().atMost(1, TimeUnit.SECONDS).until(() -> !sink.isDispatched());
+
FutureCallback fin2Callback = new FutureCallback();
ByteBuffer data2 = BufferUtil.toBuffer("Greetings Earthling", UTF_8);
sink.accept(new Frame(OpCode.BINARY).setPayload(data2).setFin(true), fin2Callback);
@@ -93,7 +95,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle);
+ InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
@@ -118,7 +120,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle);
+ InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/ReaderMessageSinkTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
index 57c2f9c1239..af3264e8d91 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
@@ -41,7 +41,7 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
- ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle);
+ ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("Hello World"), finCallback);
@@ -58,7 +58,7 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
- ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle);
+ ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/EventSocket.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/EventSocket.java
index 8568d8c0d24..b91a1d654fb 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/EventSocket.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/EventSocket.java
@@ -55,7 +55,7 @@ public class EventSocket
this.session = session;
this.endpointConfig = endpointConfig;
if (LOG.isDebugEnabled())
- LOG.debug("{} onOpen(): {}", toString(), session);
+ LOG.debug("{} onOpen(): {}", this, session);
openLatch.countDown();
}
@@ -63,7 +63,7 @@ public class EventSocket
public void onMessage(String message) throws IOException
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onMessage(): {}", toString(), message);
+ LOG.debug("{} onMessage(): {}", this, message);
textMessages.offer(message);
}
@@ -71,7 +71,7 @@ public class EventSocket
public void onMessage(ByteBuffer message) throws IOException
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onMessage(): {}", toString(), message);
+ LOG.debug("{} onMessage(): {}", this, message);
binaryMessages.offer(message);
}
@@ -79,8 +79,7 @@ public class EventSocket
public void onClose(CloseReason reason)
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onClose(): {}", toString(), reason);
-
+ LOG.debug("{} onClose(): {}", this, reason);
closeReason = reason;
closeLatch.countDown();
}
@@ -89,7 +88,7 @@ public class EventSocket
public void onError(Throwable cause)
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onError(): {}", toString(), cause);
+ LOG.debug("{} onError()", this, cause);
error = cause;
errorLatch.countDown();
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/NetworkFuzzer.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/NetworkFuzzer.java
index b93d8ffcf06..bb127c34cbc 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/NetworkFuzzer.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/NetworkFuzzer.java
@@ -229,6 +229,7 @@ public class NetworkFuzzer extends Fuzzer.Adapter implements Fuzzer, AutoCloseab
this.coreSession = coreSession;
this.openLatch.countDown();
callback.succeeded();
+ coreSession.demand(1);
}
@Override
@@ -236,6 +237,7 @@ public class NetworkFuzzer extends Fuzzer.Adapter implements Fuzzer, AutoCloseab
{
receivedFrames.offer(Frame.copy(frame));
callback.succeeded();
+ coreSession.demand(1);
}
@Override
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/framehandlers/FrameEcho.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/framehandlers/FrameEcho.java
index 58d838fbf02..0a8de6276e2 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/framehandlers/FrameEcho.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/framehandlers/FrameEcho.java
@@ -32,6 +32,7 @@ public class FrameEcho implements FrameHandler
{
this.coreSession = coreSession;
callback.succeeded();
+ coreSession.demand(1);
}
@Override
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/CloseInOnOpenTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/CloseInOnOpenTest.java
index 08262a4c35c..eb8a4ed5348 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/CloseInOnOpenTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/CloseInOnOpenTest.java
@@ -73,7 +73,7 @@ public class CloseInOnOpenTest
}
@Test
- public void testCloseInOnWebSocketConnect() throws Exception
+ public void testCloseInOnWebSocketOpen() throws Exception
{
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/ws");
EventSocket clientEndpoint = new EventSocket();
@@ -89,7 +89,7 @@ public class CloseInOnOpenTest
public static class ClosingListener
{
@OnOpen
- public void onWebSocketConnect(Session session) throws Exception
+ public void onWebSocketOpen(Session session) throws Exception
{
session.close(new CloseReason(CloseReason.CloseCodes.VIOLATED_POLICY, "I am a WS that closes immediately"));
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/JakartaClientShutdownWithServerWebAppTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/JakartaClientShutdownWithServerWebAppTest.java
index 03d7436a576..0a9df6bd856 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/JakartaClientShutdownWithServerWebAppTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/JakartaClientShutdownWithServerWebAppTest.java
@@ -38,11 +38,13 @@ import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.client.CoreClientUpgradeRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Isolated;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
+@Isolated
public class JakartaClientShutdownWithServerWebAppTest
{
private WSServer server;
@@ -175,14 +177,15 @@ public class JakartaClientShutdownWithServerWebAppTest
assertThat(response.getStatus(), is(HttpStatus.OK_200));
// Collect the toString result of the ShutdownContainers from the dump.
- List results = Arrays.stream(server.getServer().dump().split("\n"))
+ String dump = server.getServer().dump();
+ List results = Arrays.stream(dump.split("\n"))
.filter(line -> line.contains("+> " + JakartaWebSocketShutdownContainer.class.getSimpleName())).toList();
// We only have 3 Shutdown Containers and they all contain only 1 item to be shutdown.
- assertThat(results.size(), is(3));
+ assertThat(dump, results.size(), is(3));
for (String result : results)
{
- assertThat(result, containsString("size=1"));
+ assertThat(dump, result, containsString("size=1"));
}
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/autobahn/JakartaAutobahnSocket.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/autobahn/JakartaAutobahnSocket.java
index 6241d7986c6..f40c49749bf 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/autobahn/JakartaAutobahnSocket.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/autobahn/JakartaAutobahnSocket.java
@@ -37,7 +37,7 @@ public class JakartaAutobahnSocket
public CountDownLatch closeLatch = new CountDownLatch(1);
@OnOpen
- public void onConnect(Session session)
+ public void onOpen(Session session)
{
this.session = session;
session.setMaxTextMessageBufferSize(Integer.MAX_VALUE);
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/JettyWebSocketServerContainer.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/JettyWebSocketServerContainer.java
index 2c0f1683f5c..90391e09030 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/JettyWebSocketServerContainer.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/JettyWebSocketServerContainer.java
@@ -37,10 +37,9 @@ import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.LifeCycle;
+import org.eclipse.jetty.websocket.api.Configurable;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketContainer;
-import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
import org.eclipse.jetty.websocket.common.SessionTracker;
import org.eclipse.jetty.websocket.core.Configuration;
@@ -56,7 +55,7 @@ import org.eclipse.jetty.websocket.core.util.ReflectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class JettyWebSocketServerContainer extends ContainerLifeCycle implements WebSocketContainer, WebSocketPolicy, LifeCycle.Listener
+public class JettyWebSocketServerContainer extends ContainerLifeCycle implements WebSocketContainer, Configurable, LifeCycle.Listener
{
public static final String JETTY_WEBSOCKET_CONTAINER_ATTRIBUTE = WebSocketContainer.class.getName();
@@ -284,96 +283,102 @@ public class JettyWebSocketServerContainer extends ContainerLifeCycle implements
return sessionTracker.getSessions();
}
- @Override
- public WebSocketBehavior getBehavior()
- {
- return WebSocketBehavior.SERVER;
- }
-
@Override
public Duration getIdleTimeout()
{
return customizer.getIdleTimeout();
}
- @Override
- public int getInputBufferSize()
- {
- return customizer.getInputBufferSize();
- }
-
- @Override
- public int getOutputBufferSize()
- {
- return customizer.getOutputBufferSize();
- }
-
- @Override
- public long getMaxBinaryMessageSize()
- {
- return customizer.getMaxBinaryMessageSize();
- }
-
- @Override
- public long getMaxTextMessageSize()
- {
- return customizer.getMaxTextMessageSize();
- }
-
- @Override
- public long getMaxFrameSize()
- {
- return customizer.getMaxFrameSize();
- }
-
- @Override
- public boolean isAutoFragment()
- {
- return customizer.isAutoFragment();
- }
-
@Override
public void setIdleTimeout(Duration duration)
{
customizer.setIdleTimeout(duration);
}
+ @Override
+ public int getInputBufferSize()
+ {
+ return customizer.getInputBufferSize();
+ }
+
@Override
public void setInputBufferSize(int size)
{
customizer.setInputBufferSize(size);
}
+ @Override
+ public int getOutputBufferSize()
+ {
+ return customizer.getOutputBufferSize();
+ }
+
@Override
public void setOutputBufferSize(int size)
{
customizer.setOutputBufferSize(size);
}
+ @Override
+ public long getMaxBinaryMessageSize()
+ {
+ return customizer.getMaxBinaryMessageSize();
+ }
+
@Override
public void setMaxBinaryMessageSize(long size)
{
customizer.setMaxBinaryMessageSize(size);
}
+ @Override
+ public long getMaxTextMessageSize()
+ {
+ return customizer.getMaxTextMessageSize();
+ }
+
@Override
public void setMaxTextMessageSize(long size)
{
customizer.setMaxTextMessageSize(size);
}
+ @Override
+ public long getMaxFrameSize()
+ {
+ return customizer.getMaxFrameSize();
+ }
+
@Override
public void setMaxFrameSize(long maxFrameSize)
{
customizer.setMaxFrameSize(maxFrameSize);
}
+ @Override
+ public boolean isAutoFragment()
+ {
+ return customizer.isAutoFragment();
+ }
+
@Override
public void setAutoFragment(boolean autoFragment)
{
customizer.setAutoFragment(autoFragment);
}
+ @Override
+ public int getMaxOutgoingFrames()
+ {
+ return customizer.getMaxOutgoingFrames();
+ }
+
+ @Override
+ public void setMaxOutgoingFrames(int maxOutgoingFrames)
+ {
+ customizer.setMaxOutgoingFrames(maxOutgoingFrames);
+ }
+
@Override
public void dump(Appendable out, String indent) throws IOException
{
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/JettyWebSocketServletFactory.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/JettyWebSocketServletFactory.java
index 5700481e3b4..39f5886ac34 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/JettyWebSocketServletFactory.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/JettyWebSocketServletFactory.java
@@ -15,10 +15,9 @@ package org.eclipse.jetty.ee10.websocket.server;
import java.util.Set;
-import org.eclipse.jetty.websocket.api.WebSocketBehavior;
-import org.eclipse.jetty.websocket.api.WebSocketPolicy;
+import org.eclipse.jetty.websocket.api.Configurable;
-public interface JettyWebSocketServletFactory extends WebSocketPolicy
+public interface JettyWebSocketServletFactory extends Configurable
{
/**
* Add a WebSocket mapping to a provided {@link JettyWebSocketCreator}.
@@ -69,10 +68,4 @@ public interface JettyWebSocketServletFactory extends WebSocketPolicy
* @return a set the available extension names.
*/
Set getAvailableExtensionNames();
-
- @Override
- default WebSocketBehavior getBehavior()
- {
- return WebSocketBehavior.SERVER;
- }
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/test/java/org/eclipse/jetty/ee10/websocket/server/browser/BrowserSocket.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/test/java/org/eclipse/jetty/ee10/websocket/server/browser/BrowserSocket.java
index d2260c4597e..63a34ae8a76 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/test/java/org/eclipse/jetty/ee10/websocket/server/browser/BrowserSocket.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/test/java/org/eclipse/jetty/ee10/websocket/server/browser/BrowserSocket.java
@@ -16,6 +16,7 @@ package org.eclipse.jetty.ee10.websocket.server.browser;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
@@ -28,12 +29,12 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.component.Dumpable;
-import org.eclipse.jetty.websocket.api.RemoteEndpoint;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,13 +44,13 @@ public class BrowserSocket
{
private static class WriteMany implements Runnable
{
- private RemoteEndpoint remote;
+ private Session session;
private int size;
private int count;
- public WriteMany(RemoteEndpoint remote, int size, int count)
+ public WriteMany(Session session, int size, int count)
{
- this.remote = remote;
+ this.session = session;
this.size = size;
this.count = count;
}
@@ -71,7 +72,7 @@ public class BrowserSocket
randomText[i] = letters[rand.nextInt(lettersLen)];
}
msg = String.format("ManyThreads [%s]", String.valueOf(randomText));
- remote.sendString(msg, null);
+ session.sendText(msg, null);
}
}
}
@@ -88,10 +89,10 @@ public class BrowserSocket
this.requestedExtensions = reqExts;
}
- @OnWebSocketConnect
- public void onConnect(Session session)
+ @OnWebSocketOpen
+ public void onOpen(Session session)
{
- LOG.info("Connect [{}]", session);
+ LOG.info("Open [{}]", session);
this.session = session;
}
@@ -186,15 +187,9 @@ public class BrowserSocket
}
case "ping":
{
- try
- {
- LOG.info("PING!");
- this.session.getRemote().sendPing(BufferUtil.toBuffer("ping from server"));
- }
- catch (IOException e)
- {
- LOG.warn("Unable to send ping", e);
- }
+ LOG.info("PING!");
+ ByteBuffer b = BufferUtil.toBuffer("ping from server");
+ this.session.sendPing(b, Callback.NOOP);
break;
}
case "many":
@@ -218,7 +213,7 @@ public class BrowserSocket
// Setup threads
for (int n = 0; n < threadCount; n++)
{
- threads[n] = new Thread(new WriteMany(session.getRemote(), size, count), "WriteMany[" + n + "]");
+ threads[n] = new Thread(new WriteMany(session, size, count), "WriteMany[" + n + "]");
}
// Execute threads
@@ -289,7 +284,7 @@ public class BrowserSocket
}
// Async write
- session.getRemote().sendString(message, null);
+ session.sendText(message, null);
}
private void writeMessage(String format, Object... args)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/CloseInOnOpenTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/CloseInOnOpenTest.java
index e1810f05fd7..c8b810199c6 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/CloseInOnOpenTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/CloseInOnOpenTest.java
@@ -21,9 +21,9 @@ import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServerContainer;
import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.api.WebSocketConnectionListener;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@@ -72,7 +72,7 @@ public class CloseInOnOpenTest
}
@Test
- public void testCloseInOnWebSocketConnect() throws Exception
+ public void testCloseInOnWebSocketOpen() throws Exception
{
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/ws");
EventSocket clientEndpoint = new EventSocket();
@@ -84,12 +84,12 @@ public class CloseInOnOpenTest
assertThat(serverContainer.getOpenSessions().size(), is(0));
}
- public static class ClosingListener implements WebSocketConnectionListener
+ public static class ClosingListener implements Session.Listener
{
@Override
- public void onWebSocketConnect(Session session)
+ public void onWebSocketOpen(Session session)
{
- session.close(StatusCode.POLICY_VIOLATION, "I am a WS that closes immediately");
+ session.close(StatusCode.POLICY_VIOLATION, "I am a WS that closes immediately", Callback.NOOP);
}
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/EchoSocket.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/EchoSocket.java
index a7f759c0e1c..d3eea015991 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/EchoSocket.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/EchoSocket.java
@@ -16,9 +16,9 @@ package org.eclipse.jetty.ee10.websocket.tests;
import java.io.IOException;
import java.nio.ByteBuffer;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
-@SuppressWarnings("unused")
@WebSocket
public class EchoSocket extends EventSocket
{
@@ -26,13 +26,13 @@ public class EchoSocket extends EventSocket
public void onMessage(String message) throws IOException
{
super.onMessage(message);
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
}
@Override
- public void onMessage(byte[] buf, int offset, int len) throws IOException
+ public void onMessage(ByteBuffer message, Callback callback)
{
- super.onMessage(buf, offset, len);
- session.getRemote().sendBytes(ByteBuffer.wrap(buf, offset, len));
+ super.onMessage(message, Callback.NOOP);
+ session.sendBinary(message, callback);
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/EventSocket.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/EventSocket.java
index 866e9256417..9fa65cd008b 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/EventSocket.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/EventSocket.java
@@ -19,12 +19,14 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import org.eclipse.jetty.util.BlockingArrayQueue;
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +37,6 @@ public class EventSocket
private static final Logger LOG = LoggerFactory.getLogger(EventSocket.class);
public Session session;
- private String behavior;
public BlockingQueue textMessages = new BlockingArrayQueue<>();
public BlockingQueue binaryMessages = new BlockingArrayQueue<>();
@@ -47,11 +48,10 @@ public class EventSocket
public CountDownLatch errorLatch = new CountDownLatch(1);
public CountDownLatch closeLatch = new CountDownLatch(1);
- @OnWebSocketConnect
+ @OnWebSocketOpen
public void onOpen(Session session)
{
this.session = session;
- behavior = session.getPolicy().getBehavior().name();
if (LOG.isDebugEnabled())
LOG.debug("{} onOpen(): {}", this, session);
openLatch.countDown();
@@ -66,12 +66,12 @@ public class EventSocket
}
@OnWebSocketMessage
- public void onMessage(byte[] buf, int offset, int len) throws IOException
+ public void onMessage(ByteBuffer message, Callback callback)
{
- ByteBuffer message = ByteBuffer.wrap(buf, offset, len);
if (LOG.isDebugEnabled())
LOG.debug("{} onMessage(): {}", this, message);
- binaryMessages.offer(message);
+ binaryMessages.offer(BufferUtil.copy(message));
+ callback.succeed();
}
@OnWebSocketClose
@@ -88,7 +88,7 @@ public class EventSocket
public void onError(Throwable cause)
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onError(): {}", this, cause);
+ LOG.debug("{} onError()", this, cause);
error = cause;
errorLatch.countDown();
}
@@ -96,6 +96,6 @@ public class EventSocket
@Override
public String toString()
{
- return String.format("[%s@%s]", behavior, Integer.toHexString(hashCode()));
+ return String.format("[%s@%x]", getClass().getSimpleName(), hashCode());
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyClientClassLoaderTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyClientClassLoaderTest.java
index bfd400a7b47..2b4cd4e104b 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyClientClassLoaderTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyClientClassLoaderTest.java
@@ -34,10 +34,11 @@ import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
+import org.eclipse.jetty.websocket.api.Callback;
+import org.eclipse.jetty.websocket.api.Configurable;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketPolicy;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.common.WebSocketSession;
@@ -84,10 +85,10 @@ public class JettyClientClassLoaderTest
{
LinkedBlockingQueue textMessages = new LinkedBlockingQueue<>();
- @OnWebSocketConnect
+ @OnWebSocketOpen
public void onOpen(Session session) throws Exception
{
- session.getRemote().sendString("ContextClassLoader: " + Thread.currentThread().getContextClassLoader());
+ session.sendText("ContextClassLoader: " + Thread.currentThread().getContextClassLoader(), Callback.NOOP);
}
@OnWebSocketMessage
@@ -152,7 +153,7 @@ public class JettyClientClassLoaderTest
@OnWebSocketMessage
public void onMessage(Session session, String message) throws Exception
{
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
}
}
@@ -162,7 +163,7 @@ public class JettyClientClassLoaderTest
// Copy over the individual jars required for Javax WebSocket.
app.createWebInf();
- app.copyLib(WebSocketPolicy.class, "jetty-websocket-jetty-api.jar");
+ app.copyLib(Configurable.class, "jetty-websocket-jetty-api.jar");
app.copyLib(WebSocketClient.class, "jetty-websocket-jetty-client.jar");
app.copyLib(WebSocketSession.class, "jetty-websocket-jetty-common.jar");
app.copyLib(ContainerLifeCycle.class, "jetty-util.jar");
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketFilterTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketFilterTest.java
index 6a12637b51a..9f64616172c 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketFilterTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketFilterTest.java
@@ -42,6 +42,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@@ -124,7 +125,7 @@ public class JettyWebSocketFilterTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello world");
+ session.sendText("hello world", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(10, TimeUnit.SECONDS));
@@ -158,7 +159,7 @@ public class JettyWebSocketFilterTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello world");
+ session.sendText("hello world", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(10, TimeUnit.SECONDS));
@@ -195,7 +196,7 @@ public class JettyWebSocketFilterTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello world");
+ session.sendText("hello world", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(10, TimeUnit.SECONDS));
@@ -253,8 +254,8 @@ public class JettyWebSocketFilterTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hElLo wOrLd");
- session.getRemote().sendString("getIdleTimeout");
+ session.sendText("hElLo wOrLd", Callback.NOOP);
+ session.sendText("getIdleTimeout", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(socket.textMessages.poll(), is("hello world"));
@@ -266,8 +267,8 @@ public class JettyWebSocketFilterTest
connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hElLo wOrLd");
- session.getRemote().sendString("getIdleTimeout");
+ session.sendText("hElLo wOrLd", Callback.NOOP);
+ session.sendText("getIdleTimeout", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(socket.textMessages.poll(), is("HELLO WORLD"));
@@ -297,7 +298,7 @@ public class JettyWebSocketFilterTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hElLo wOrLd");
+ session.sendText("hElLo wOrLd", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(socket.textMessages.poll(), is("hElLo wOrLd"));
@@ -329,8 +330,8 @@ public class JettyWebSocketFilterTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello world");
- session.getRemote().sendString("getIdleTimeout");
+ session.sendText("hello world", Callback.NOOP);
+ session.sendText("getIdleTimeout", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(socket.textMessages.poll(), is("hello world"));
@@ -363,8 +364,8 @@ public class JettyWebSocketFilterTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello world");
- session.getRemote().sendString("getIdleTimeout");
+ session.sendText("hello world", Callback.NOOP);
+ session.sendText("getIdleTimeout", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(socket.textMessages.poll(), is("hello world"));
@@ -388,9 +389,9 @@ public class JettyWebSocketFilterTest
public void onMessage(Session session, String message) throws IOException
{
if ("getIdleTimeout".equals(message))
- session.getRemote().sendString(Long.toString(session.getIdleTimeout().toMillis()));
+ session.sendText(Long.toString(session.getIdleTimeout().toMillis()), Callback.NOOP);
else
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
}
}
}
@@ -413,9 +414,9 @@ public class JettyWebSocketFilterTest
public void onMessage(Session session, String message) throws IOException
{
if ("getIdleTimeout".equals(message))
- session.getRemote().sendString(Long.toString(session.getIdleTimeout().toMillis()));
+ session.sendText(Long.toString(session.getIdleTimeout().toMillis()), Callback.NOOP);
else
- session.getRemote().sendString(message.toLowerCase());
+ session.sendText(message.toLowerCase(), Callback.NOOP);
}
}
@@ -426,9 +427,9 @@ public class JettyWebSocketFilterTest
public void onMessage(Session session, String message) throws IOException
{
if ("getIdleTimeout".equals(message))
- session.getRemote().sendString(Long.toString(session.getIdleTimeout().toMillis()));
+ session.sendText(Long.toString(session.getIdleTimeout().toMillis()), Callback.NOOP);
else
- session.getRemote().sendString(message.toUpperCase());
+ session.sendText(message.toUpperCase(), Callback.NOOP);
}
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketRestartTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketRestartTest.java
index 6da5e7393c8..05bfdecffab 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketRestartTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketRestartTest.java
@@ -24,6 +24,7 @@ import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletConta
import org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents;
@@ -112,7 +113,7 @@ public class JettyWebSocketRestartTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello world");
+ session.sendText("hello world", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(10, TimeUnit.SECONDS));
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletAttributeTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletAttributeTest.java
index a351742b8cd..1aa1f8589ac 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletAttributeTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletAttributeTest.java
@@ -25,8 +25,8 @@ import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WriteCallback;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -118,7 +118,7 @@ public class JettyWebSocketServletAttributeTest
EventSocket clientEndpoint = new EventSocket();
try (Session session = client.connect(clientEndpoint, uri).get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello", WriteCallback.NOOP);
+ session.sendText("hello", Callback.NOOP);
String path = clientEndpoint.textMessages.poll(5, TimeUnit.SECONDS);
assertEquals(param, path);
}
@@ -137,7 +137,7 @@ public class JettyWebSocketServletAttributeTest
@OnWebSocketMessage
public void onText(Session session, String text) throws IOException
{
- session.getRemote().sendString(param);
+ session.sendText(param, Callback.NOOP);
}
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletTest.java
index c1802eb8169..988fe64e414 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletTest.java
@@ -23,6 +23,7 @@ import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServletFactory;
import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.junit.jupiter.api.AfterEach;
@@ -83,7 +84,7 @@ public class JettyWebSocketServletTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello world");
+ session.sendText("hello world", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(10, TimeUnit.SECONDS));
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/MyBinaryEchoSocket.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/MyBinaryEchoSocket.java
index 40d8bcb864a..2bb9c620f9d 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/MyBinaryEchoSocket.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/MyBinaryEchoSocket.java
@@ -29,6 +29,6 @@ public class MyBinaryEchoSocket
public void onWebSocketText(Session session, byte[] buf, int offset, int len)
{
// Echo message back, asynchronously
- session.getRemote().sendBytes(ByteBuffer.wrap(buf, offset, len), null);
+ session.sendBinary(ByteBuffer.wrap(buf, offset, len), null);
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/MyEchoSocket.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/MyEchoSocket.java
index 45ea5e82b0a..4f89c271173 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/MyEchoSocket.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/MyEchoSocket.java
@@ -27,6 +27,6 @@ public class MyEchoSocket
public void onWebSocketText(Session session, String message)
{
// Echo message back, asynchronously
- session.getRemote().sendString(message, null);
+ session.sendText(message, null);
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/PermessageDeflateBufferTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/PermessageDeflateBufferTest.java
index 6b5e706adda..5c20184d797 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/PermessageDeflateBufferTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/PermessageDeflateBufferTest.java
@@ -13,7 +13,6 @@
package org.eclipse.jetty.ee10.websocket.tests;
-import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.time.Duration;
@@ -35,11 +34,12 @@ import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.compression.CompressionPool;
import org.eclipse.jetty.util.compression.DeflaterPool;
import org.eclipse.jetty.util.compression.InflaterPool;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -48,8 +48,6 @@ import org.eclipse.jetty.websocket.core.WebSocketCoreSession;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
@@ -155,7 +153,7 @@ public class PermessageDeflateBufferTest
Session session = client.connect(socket, uri, clientUpgradeRequest).get(5, TimeUnit.SECONDS);
String s = randomText();
- session.getRemote().sendString(s);
+ session.sendText(s, Callback.NOOP);
assertThat(socket.textMessages.poll(5, TimeUnit.SECONDS), is(s));
session.close();
@@ -175,7 +173,7 @@ public class PermessageDeflateBufferTest
ByteBuffer message = randomBytes(1024);
session.setMaxFrameSize(64);
- session.getRemote().sendBytes(message);
+ session.sendBinary(message, Callback.NOOP);
assertThat(socket.binaryMessages.poll(5, TimeUnit.SECONDS), equalTo(message));
session.close();
@@ -196,7 +194,7 @@ public class PermessageDeflateBufferTest
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/incomingFail");
Session session = client.connect(socket, uri, clientUpgradeRequest).get(5, TimeUnit.SECONDS);
- session.getRemote().sendPartialString("partial", false);
+ session.sendPartialText("partial", false, Callback.NOOP);
// Wait for the idle timeout to elapse.
assertTrue(incomingFailEndPoint.closeLatch.await(5, TimeUnit.SECONDS));
@@ -219,7 +217,7 @@ public class PermessageDeflateBufferTest
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/incomingFail");
Session session = client.connect(socket, uri, clientUpgradeRequest).get(5, TimeUnit.SECONDS);
- session.getRemote().sendPartialString("partial", false);
+ session.sendPartialText("partial", false, Callback.NOOP);
// Wait for the server to process the partial message.
assertThat(socket.partialMessages.poll(5, TimeUnit.SECONDS), equalTo("partial" + "last=true"));
@@ -250,7 +248,7 @@ public class PermessageDeflateBufferTest
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/outgoingFail");
Session session = client.connect(socket, uri, clientUpgradeRequest).get(5, TimeUnit.SECONDS);
- session.getRemote().sendString("hello");
+ session.sendText("hello", Callback.NOOP);
// Wait for the idle timeout to elapse.
assertTrue(outgoingFailEndPoint.closeLatch.await(2 * idleTimeout.toMillis(), TimeUnit.SECONDS));
@@ -273,7 +271,7 @@ public class PermessageDeflateBufferTest
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/outgoingFail");
Session session = client.connect(socket, uri, clientUpgradeRequest).get(5, TimeUnit.SECONDS);
- session.getRemote().sendString("hello");
+ session.sendText("hello", Callback.NOOP);
// Wait for the server to process the message.
assertThat(socket.partialMessages.poll(5, TimeUnit.SECONDS), equalTo("hello" + "last=false"));
@@ -294,14 +292,12 @@ public class PermessageDeflateBufferTest
@WebSocket
public static class PartialTextSocket
{
- private static final Logger LOG = LoggerFactory.getLogger(EventSocket.class);
-
public Session session;
public BlockingQueue partialMessages = new BlockingArrayQueue<>();
public CountDownLatch openLatch = new CountDownLatch(1);
public CountDownLatch closeLatch = new CountDownLatch(1);
- @OnWebSocketConnect
+ @OnWebSocketOpen
public void onOpen(Session session)
{
this.session = session;
@@ -309,7 +305,7 @@ public class PermessageDeflateBufferTest
}
@OnWebSocketMessage
- public void onMessage(String message, boolean last) throws IOException
+ public void onMessage(String message, boolean last)
{
partialMessages.offer(message + "last=" + last);
}
@@ -327,9 +323,9 @@ public class PermessageDeflateBufferTest
public CountDownLatch closeLatch = new CountDownLatch(1);
@OnWebSocketMessage
- public void onMessage(Session session, String message) throws IOException
+ public void onMessage(Session session, String message)
{
- session.getRemote().sendPartialString(message, false);
+ session.sendPartialText(message, false, Callback.NOOP);
}
@OnWebSocketClose
@@ -345,9 +341,9 @@ public class PermessageDeflateBufferTest
public CountDownLatch closeLatch = new CountDownLatch(1);
@OnWebSocketMessage
- public void onMessage(Session session, String message, boolean last) throws IOException
+ public void onMessage(Session session, String message, boolean last)
{
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
}
@OnWebSocketClose
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/ProgrammaticWebSocketUpgradeTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/ProgrammaticWebSocketUpgradeTest.java
index ae1a9aebe38..3ca8d1bcabe 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/ProgrammaticWebSocketUpgradeTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/ProgrammaticWebSocketUpgradeTest.java
@@ -30,6 +30,7 @@ import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServerContainer;
import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.junit.jupiter.api.AfterEach;
@@ -101,7 +102,7 @@ public class ProgrammaticWebSocketUpgradeTest
CompletableFuture connect = client.connect(socket, uri);
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
- session.getRemote().sendString("hello world");
+ session.sendText("hello world", Callback.NOOP);
}
assertTrue(socket.closeLatch.await(10, TimeUnit.SECONDS));
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/ServerConfigTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/ServerConfigTest.java
index e29f3b79d89..064b81ccb0a 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/ServerConfigTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/ServerConfigTest.java
@@ -14,6 +14,7 @@
package org.eclipse.jetty.ee10.websocket.tests;
import java.net.URI;
+import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
@@ -30,7 +31,7 @@ import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.websocket.api.BatchMode;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@@ -64,7 +65,6 @@ public class ServerConfigTest
private static final int MAX_MESSAGE_SIZE = 20;
private static final int IDLE_TIMEOUT = 500;
- private final EventSocket annotatedEndpoint = new AnnotatedConfigEndpoint();
private final EventSocket sessionConfigEndpoint = new SessionConfigEndpoint();
private final EventSocket standardEndpoint = new EventSocket();
@@ -73,7 +73,6 @@ public class ServerConfigTest
return switch (path)
{
case "servletConfig", "containerConfig" -> standardEndpoint;
- case "annotatedConfig" -> annotatedEndpoint;
case "sessionConfig" -> sessionConfigEndpoint;
default -> throw new IllegalStateException();
};
@@ -81,12 +80,7 @@ public class ServerConfigTest
public static Stream data()
{
- return Stream.of("servletConfig", "annotatedConfig", "containerConfig", "sessionConfig").map(Arguments::of);
- }
-
- @WebSocket(idleTimeout = IDLE_TIMEOUT, maxTextMessageSize = MAX_MESSAGE_SIZE, maxBinaryMessageSize = MAX_MESSAGE_SIZE, inputBufferSize = INPUT_BUFFER_SIZE, batchMode = BatchMode.ON)
- public static class AnnotatedConfigEndpoint extends EventSocket
- {
+ return Stream.of("servletConfig", "containerConfig", "sessionConfig").map(Arguments::of);
}
@WebSocket
@@ -116,15 +110,6 @@ public class ServerConfigTest
}
}
- public class WebSocketAnnotatedConfigServlet extends JettyWebSocketServlet
- {
- @Override
- public void configure(JettyWebSocketServletFactory factory)
- {
- factory.addMapping("/", (req, resp) -> annotatedEndpoint);
- }
- }
-
public class WebSocketSessionConfigServlet extends JettyWebSocketServlet
{
@Override
@@ -171,7 +156,6 @@ public class ServerConfigTest
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setContextPath("/");
contextHandler.addServlet(new ServletHolder(new WebSocketFactoryConfigServlet()), "/servletConfig");
- contextHandler.addServlet(new ServletHolder(new WebSocketAnnotatedConfigServlet()), "/annotatedConfig");
contextHandler.addServlet(new ServletHolder(new WebSocketSessionConfigServlet()), "/sessionConfig");
server.setHandler(contextHandler);
@@ -234,7 +218,8 @@ public class ServerConfigTest
CompletableFuture connect = client.connect(clientEndpoint, uri);
connect.get(5, TimeUnit.SECONDS);
- clientEndpoint.session.getRemote().sendBytes(BufferUtil.toBuffer(MESSAGE));
+ ByteBuffer buffer = BufferUtil.toBuffer(MESSAGE);
+ clientEndpoint.session.sendBinary(buffer, Callback.NOOP);
assertTrue(serverEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(serverEndpoint.error, instanceOf(MessageTooLargeException.class));
@@ -255,7 +240,7 @@ public class ServerConfigTest
CompletableFuture connect = client.connect(clientEndpoint, uri);
connect.get(5, TimeUnit.SECONDS);
- clientEndpoint.session.getRemote().sendString("hello world");
+ clientEndpoint.session.sendText("hello world", Callback.NOOP);
String msg = serverEndpoint.textMessages.poll(500, TimeUnit.MILLISECONDS);
assertThat(msg, is("hello world"));
Thread.sleep(IDLE_TIMEOUT + 500);
@@ -279,7 +264,7 @@ public class ServerConfigTest
CompletableFuture connect = client.connect(clientEndpoint, uri);
connect.get(5, TimeUnit.SECONDS);
- clientEndpoint.session.getRemote().sendString(MESSAGE);
+ clientEndpoint.session.sendText(MESSAGE, Callback.NOOP);
assertTrue(serverEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
assertThat(serverEndpoint.error, instanceOf(MessageTooLargeException.class));
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/WebSocketOverHTTP2Test.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/WebSocketOverHTTP2Test.java
index 9e3cb9c7914..0bab0daac55 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/WebSocketOverHTTP2Test.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/WebSocketOverHTTP2Test.java
@@ -58,8 +58,10 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.internal.HttpChannelState;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.exceptions.UpgradeException;
@@ -104,7 +106,7 @@ public class WebSocketOverHTTP2Test
server.addConnector(connector);
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
- sslContextFactory.setKeyStorePath("src/test/resources/keystore.p12");
+ sslContextFactory.setKeyStorePath(MavenTestingUtils.getTestResourcePath("keystore.p12").toString());
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR);
@@ -168,13 +170,13 @@ public class WebSocketOverHTTP2Test
Session session = wsClient.connect(wsEndPoint, uri).get(5, TimeUnit.SECONDS);
String text = "websocket";
- session.getRemote().sendString(text);
+ session.sendText(text, Callback.NOOP);
String message = wsEndPoint.textMessages.poll(5, TimeUnit.SECONDS);
assertNotNull(message);
assertEquals(text, message);
- session.close(StatusCode.NORMAL, null);
+ session.close(StatusCode.NORMAL, null, Callback.NOOP);
assertTrue(wsEndPoint.closeLatch.await(5, TimeUnit.SECONDS));
assertEquals(StatusCode.NORMAL, wsEndPoint.closeCode);
assertNull(wsEndPoint.error);
@@ -231,13 +233,13 @@ public class WebSocketOverHTTP2Test
URI uri = URI.create("wss://localhost:" + tlsConnector.getLocalPort() + "/ws/echo");
Session session = wsClient.connect(wsEndPoint, uri).get(5, TimeUnit.SECONDS);
String text = "websocket";
- session.getRemote().sendString(text);
+ session.sendText(text, Callback.NOOP);
String message = wsEndPoint.textMessages.poll(5, TimeUnit.SECONDS);
assertNotNull(message);
assertEquals(text, message);
- session.close(StatusCode.NORMAL, null);
+ session.close(StatusCode.NORMAL, null, Callback.NOOP);
assertTrue(wsEndPoint.closeLatch.await(5, TimeUnit.SECONDS));
}
@@ -361,7 +363,7 @@ public class WebSocketOverHTTP2Test
EventSocket clientEndpoint = new EventSocket();
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/specialEcho");
Session session = wsClient.connect(clientEndpoint, uri).get(5, TimeUnit.SECONDS);
- session.getRemote().sendString("hello world");
+ session.sendText("hello world", Callback.NOOP);
String received = clientEndpoint.textMessages.poll(5, TimeUnit.SECONDS);
assertThat(received, equalTo("hello world"));
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/WebSocketServletExamplesTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/WebSocketServletExamplesTest.java
index 5da3a50ff32..ebfb4ff2861 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/WebSocketServletExamplesTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/WebSocketServletExamplesTest.java
@@ -31,6 +31,7 @@ import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.security.Credential;
+import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -112,7 +113,7 @@ public class WebSocketServletExamplesTest
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
String message = "hello world";
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
String response = socket.textMessages.poll(5, TimeUnit.SECONDS);
assertThat(response, is(message));
@@ -136,7 +137,7 @@ public class WebSocketServletExamplesTest
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
String message = "hello world";
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
String response = socket.textMessages.poll(5, TimeUnit.SECONDS);
assertThat(response, is(message));
@@ -162,7 +163,7 @@ public class WebSocketServletExamplesTest
try (Session session = connect.get(5, TimeUnit.SECONDS))
{
String message = "hello world";
- session.getRemote().sendString(message);
+ session.sendText(message, Callback.NOOP);
String response = socket.textMessages.poll(5, TimeUnit.SECONDS);
assertThat(response, is(message));
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/resources/keystore.p12 b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/resources/keystore.p12
new file mode 100644
index 00000000000..b51c835024b
Binary files /dev/null and b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/resources/keystore.p12 differ
diff --git a/jetty-ee10/jetty-ee10-websocket/pom.xml b/jetty-ee10/jetty-ee10-websocket/pom.xml
index 6ec675fd69f..e0b87510e45 100644
--- a/jetty-ee10/jetty-ee10-websocket/pom.xml
+++ b/jetty-ee10/jetty-ee10-websocket/pom.xml
@@ -27,17 +27,4 @@
jetty-ee10-websocket-servlet
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- true
-
-
-
-
-
diff --git a/jetty-ee8/jetty-ee8-websocket/jetty-ee8-websocket-javax-common/pom.xml b/jetty-ee8/jetty-ee8-websocket/jetty-ee8-websocket-javax-common/pom.xml
index b8f2c56ba74..063b9b323ca 100644
--- a/jetty-ee8/jetty-ee8-websocket/jetty-ee8-websocket-javax-common/pom.xml
+++ b/jetty-ee8/jetty-ee8-websocket/jetty-ee8-websocket-javax-common/pom.xml
@@ -47,10 +47,16 @@
org.slf4j
slf4j-api
+
org.eclipse.jetty
jetty-slf4j-impl
test
+
+ org.awaitility
+ awaitility
+ test
+
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/pom.xml b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/pom.xml
index 8161ea798f5..ef8a91d98bd 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/pom.xml
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/pom.xml
@@ -46,10 +46,16 @@
org.slf4j
slf4j-api
+
org.eclipse.jetty
jetty-slf4j-impl
test
+
+ org.awaitility
+ awaitility
+ test
+
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandler.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
index 0d913746acf..efea52a59bc 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
@@ -322,12 +322,6 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
}
}
- @Override
- public boolean isAutoDemanding()
- {
- return false;
- }
-
public Set getMessageHandlers()
{
return messageHandlerMap.values().stream()
@@ -600,6 +594,11 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
{
callback.succeeded();
coreSession.demand(1);
+ }, x ->
+ {
+ // Ignore failures, as we might be OSHUT but receive a PING.
+ callback.succeeded();
+ coreSession.demand(1);
}), false);
}
@@ -616,14 +615,19 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
// Use JSR356 PongMessage interface
JakartaWebSocketPongMessage pongMessage = new JakartaWebSocketPongMessage(payload);
pongHandle.invoke(pongMessage);
+ callback.succeeded();
+ coreSession.demand(1);
}
catch (Throwable cause)
{
- throw new WebSocketException(endpointInstance.getClass().getSimpleName() + " PONG method error: " + cause.getMessage(), cause);
+ callback.failed(new WebSocketException(endpointInstance.getClass().getSimpleName() + " PONG method error: " + cause.getMessage(), cause));
}
}
- callback.succeeded();
- coreSession.demand(1);
+ else
+ {
+ callback.succeeded();
+ coreSession.demand(1);
+ }
}
public void onText(Frame frame, Callback callback)
@@ -646,14 +650,9 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
{
switch (dataType)
{
- case OpCode.TEXT:
- onText(frame, callback);
- break;
- case OpCode.BINARY:
- onBinary(frame, callback);
- break;
- default:
- throw new ProtocolException("Unable to process continuation during dataType " + dataType);
+ case OpCode.TEXT -> onText(frame, callback);
+ case OpCode.BINARY -> onBinary(frame, callback);
+ default -> callback.failed(new ProtocolException("Unable to process continuation during dataType " + dataType));
}
}
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
index 7c4b05eada8..80e1158f2ab 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
@@ -197,8 +197,8 @@ public abstract class JakartaWebSocketFrameHandlerFactory
else
{
MethodHandle ctorHandle = lookup.findConstructor(msgMetadata.getSinkClass(),
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class));
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle());
+ MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, boolean.class));
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle(), true);
}
}
catch (NoSuchMethodException e)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
index 1f29181fdac..1eab5c76a87 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
@@ -45,7 +45,7 @@ public class DecodedBinaryMessageSink extends AbstractDecodedMessageSink.Basi
MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
.findVirtual(DecodedBinaryMessageSink.class, "onWholeMessage", MethodType.methodType(void.class, ByteBuffer.class))
.bindTo(this);
- return new ByteBufferMessageSink(coreSession, methodHandle);
+ return new ByteBufferMessageSink(coreSession, methodHandle, true);
}
public void onWholeMessage(ByteBuffer wholeMessage)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
index 9c1adc2aff1..d7d07ad4859 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
@@ -42,7 +42,7 @@ public class DecodedBinaryStreamMessageSink extends AbstractDecodedMessageSin
MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
.findVirtual(DecodedBinaryStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, InputStream.class))
.bindTo(this);
- return new InputStreamMessageSink(coreSession, methodHandle);
+ return new InputStreamMessageSink(coreSession, methodHandle, true);
}
public void onStreamStart(InputStream stream)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSink.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSink.java
index ef4bebfe2ed..e7091d4596e 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSink.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSink.java
@@ -44,7 +44,7 @@ public class DecodedTextMessageSink extends AbstractDecodedMessageSink.Basic<
MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
.findVirtual(getClass(), "onMessage", MethodType.methodType(void.class, String.class))
.bindTo(this);
- return new StringMessageSink(coreSession, methodHandle);
+ return new StringMessageSink(coreSession, methodHandle, true);
}
public void onMessage(String wholeMessage)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
index 630c4b0d25d..47993416cf1 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
@@ -42,7 +42,7 @@ public class DecodedTextStreamMessageSink extends AbstractDecodedMessageSink.
MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
.findVirtual(DecodedTextStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, Reader.class))
.bindTo(this);
- return new ReaderMessageSink(coreSession, methodHandle);
+ return new ReaderMessageSink(coreSession, methodHandle, true);
}
public void onStreamStart(Reader reader)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
index 0ef16e60493..aaa05b69ccd 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
@@ -56,7 +56,6 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
data.put((byte)31);
data.flip();
sink.accept(new Frame(OpCode.BINARY).setPayload(data).setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
Calendar decoded = copyFuture.get(1, TimeUnit.SECONDS);
assertThat("Decoded.contents", format(decoded, "MM-dd-yyyy"), is("12-31-1999"));
@@ -89,11 +88,8 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
data3.flip();
sink.accept(new Frame(OpCode.BINARY).setPayload(data1).setFin(false), callback1);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(data2).setFin(false), callback2);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(data3).setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
finCallback.get(1, TimeUnit.SECONDS); // wait for callback
Calendar decoded = copyFuture.get(1, TimeUnit.SECONDS);
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
index 0b54dd11c4b..47863ff3271 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
@@ -58,7 +58,6 @@ public class DecodedBinaryStreamMessageSinkTest extends AbstractMessageSinkTest
data.put((byte)31);
data.flip();
sink.accept(new Frame(OpCode.BINARY).setPayload(data).setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
Calendar decoded = copyFuture.get(1, TimeUnit.SECONDS);
assertThat("Decoded.contents", format(decoded, "MM-dd-yyyy"), is("12-31-1999"));
@@ -91,11 +90,8 @@ public class DecodedBinaryStreamMessageSinkTest extends AbstractMessageSinkTest
data3.flip();
sink.accept(new Frame(OpCode.BINARY).setPayload(data1).setFin(false), callback1);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(data2).setFin(false), callback2);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(data3).setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
Calendar decoded = copyFuture.get(1, TimeUnit.SECONDS);
assertThat("Decoded.contents", format(decoded, "MM-dd-yyyy"), is("01-01-2000"));
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
index 9cff849b7a9..f4c08ab3172 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
@@ -51,7 +51,6 @@ public class DecodedTextMessageSinkTest extends AbstractMessageSinkTest
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("2018.02.13").setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
Date decoded = copyFuture.get(1, TimeUnit.SECONDS);
assertThat("Decoded.contents", format(decoded, "MM-dd-yyyy"), is("02-13-2018"));
@@ -72,11 +71,8 @@ public class DecodedTextMessageSinkTest extends AbstractMessageSinkTest
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("2023").setFin(false), callback1);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(".08").setFin(false), callback2);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(".22").setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
Date decoded = copyFuture.get(1, TimeUnit.SECONDS);
assertThat("Decoded.contents", format(decoded, "MM-dd-yyyy"), is("08-22-2023"));
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
index 8a661836365..4dd8cd533ee 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
@@ -54,7 +54,6 @@ public class DecodedTextStreamMessageSinkTest extends AbstractMessageSinkTest
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("2018.02.13").setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
Date decoded = copyFuture.get(1, TimeUnit.SECONDS);
assertThat("Decoded.contents", format(decoded, "MM-dd-yyyy"), is("02-13-2018"));
@@ -75,11 +74,8 @@ public class DecodedTextStreamMessageSinkTest extends AbstractMessageSinkTest
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("2023").setFin(false), callback1);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(".08").setFin(false), callback2);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(".22").setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
Date decoded = copyFuture.get(1, TimeUnit.SECONDS);
assertThat("Decoded.contents", format(decoded, "MM-dd-yyyy"), is("08-22-2023"));
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
index 23e9f2923a5..56ccec6089a 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
@@ -36,6 +36,7 @@ import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.awaitility.Awaitility.await;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -46,13 +47,12 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle);
+ InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle, true);
FutureCallback finCallback = new FutureCallback();
ByteBuffer data = BufferUtil.toBuffer("Hello World", UTF_8);
sink.accept(new Frame(OpCode.BINARY).setPayload(data), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
finCallback.get(1, TimeUnit.SECONDS);
ByteArrayOutputStream byteStream = copy.poll(1, TimeUnit.SECONDS);
assertThat("Writer.contents", byteStream.toString(UTF_8), is("Hello World"));
@@ -64,24 +64,23 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle);
+ InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle, true);
FutureCallback fin1Callback = new FutureCallback();
ByteBuffer data1 = BufferUtil.toBuffer("Hello World", UTF_8);
sink.accept(new Frame(OpCode.BINARY).setPayload(data1).setFin(true), fin1Callback);
- // wait for demand (can't sent next message until a new frame is demanded)
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
fin1Callback.get(1, TimeUnit.SECONDS);
ByteArrayOutputStream byteStream = copy.poll(1, TimeUnit.SECONDS);
assertThat("Writer.contents", byteStream.toString(UTF_8), is("Hello World"));
assertThat("FinCallback.done", fin1Callback.isDone(), is(true));
+ await().atMost(1, TimeUnit.SECONDS).until(() -> !sink.isDispatched());
+
FutureCallback fin2Callback = new FutureCallback();
ByteBuffer data2 = BufferUtil.toBuffer("Greetings Earthling", UTF_8);
sink.accept(new Frame(OpCode.BINARY).setPayload(data2).setFin(true), fin2Callback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
fin2Callback.get(1, TimeUnit.SECONDS);
byteStream = copy.poll(1, TimeUnit.SECONDS);
assertThat("Writer.contents", byteStream.toString(UTF_8), is("Greetings Earthling"));
@@ -93,18 +92,15 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle);
+ InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.BINARY).setPayload("Hello").setFin(false), callback1);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(", ").setFin(false), callback2);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload("World").setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
ByteArrayOutputStream byteStream = copy.poll(1, TimeUnit.SECONDS);
assertThat("Writer.contents", byteStream.toString(UTF_8), is("Hello, World"));
@@ -118,7 +114,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle);
+ InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
@@ -126,13 +122,9 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.BINARY).setPayload("Greetings").setFin(false), callback1);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(", ").setFin(false), callback2);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload("Earthling").setFin(false), callback3);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(new byte[0]).setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
ByteArrayOutputStream byteStream = copy.poll(1, TimeUnit.SECONDS);
assertThat("Writer.contents", byteStream.toString(UTF_8), is("Greetings, Earthling"));
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/ReaderMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
index 828abd72e3d..795422ecc4f 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
@@ -41,11 +41,10 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
- ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle);
+ ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("Hello World"), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
StringWriter writer = copyFuture.get(1, TimeUnit.SECONDS);
assertThat("Writer.contents", writer.getBuffer().toString(), is("Hello World"));
@@ -58,18 +57,15 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
- ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle);
+ ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("Hello").setFin(false), callback1);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload(", ").setFin(false), callback2);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
sink.accept(new Frame(OpCode.CONTINUATION).setPayload("World").setFin(true), finCallback);
- coreSession.waitForDemand(1, TimeUnit.SECONDS);
StringWriter writer = copyFuture.get(1, TimeUnit.SECONDS);
assertThat("Writer contents", writer.getBuffer().toString(), is("Hello, World"));
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/NetworkFuzzer.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/NetworkFuzzer.java
index 0e62e36dd1f..201b31b9dda 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/NetworkFuzzer.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/NetworkFuzzer.java
@@ -229,6 +229,7 @@ public class NetworkFuzzer extends Fuzzer.Adapter implements Fuzzer, AutoCloseab
this.coreSession = coreSession;
this.openLatch.countDown();
callback.succeeded();
+ coreSession.demand(1);
}
@Override
@@ -236,6 +237,7 @@ public class NetworkFuzzer extends Fuzzer.Adapter implements Fuzzer, AutoCloseab
{
receivedFrames.offer(Frame.copy(frame));
callback.succeeded();
+ coreSession.demand(1);
}
@Override
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/framehandlers/FrameEcho.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/framehandlers/FrameEcho.java
index 62f2ec69472..79314e3c1cf 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/framehandlers/FrameEcho.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/framehandlers/FrameEcho.java
@@ -32,15 +32,22 @@ public class FrameEcho implements FrameHandler
{
this.coreSession = coreSession;
callback.succeeded();
+ coreSession.demand(1);
}
@Override
public void onFrame(Frame frame, Callback callback)
{
- if (frame.isControlFrame())
+ Runnable succeedAndDemand = () ->
+ {
callback.succeeded();
+ coreSession.demand(1);
+ };
+
+ if (frame.isControlFrame())
+ succeedAndDemand.run();
else
- coreSession.sendFrame(Frame.copy(frame), callback, false);
+ coreSession.sendFrame(Frame.copy(frame), Callback.from(succeedAndDemand, callback::failed), false);
}
@Override
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/CloseInOnOpenTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/CloseInOnOpenTest.java
index 9dc383df543..29170635ba9 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/CloseInOnOpenTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/CloseInOnOpenTest.java
@@ -73,7 +73,7 @@ public class CloseInOnOpenTest
}
@Test
- public void testCloseInOnWebSocketConnect() throws Exception
+ public void testCloseInOnWebSocketOpen() throws Exception
{
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/ws");
EventSocket clientEndpoint = new EventSocket();
@@ -89,7 +89,7 @@ public class CloseInOnOpenTest
public static class ClosingListener
{
@OnOpen
- public void onWebSocketConnect(Session session) throws Exception
+ public void onWebSocketOpen(Session session) throws Exception
{
session.close(new CloseReason(CloseReason.CloseCodes.VIOLATED_POLICY, "I am a WS that closes immediately"));
}
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/autobahn/JakartaAutobahnSocket.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/autobahn/JakartaAutobahnSocket.java
index 14664b91896..f3949f875d8 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/autobahn/JakartaAutobahnSocket.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/autobahn/JakartaAutobahnSocket.java
@@ -37,7 +37,7 @@ public class JakartaAutobahnSocket
public CountDownLatch closeLatch = new CountDownLatch(1);
@OnOpen
- public void onConnect(Session session)
+ public void onOpen(Session session)
{
this.session = session;
session.setMaxTextMessageBufferSize(Integer.MAX_VALUE);
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandler.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandler.java
index 2c113553c97..7de2dcb48ab 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandler.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandler.java
@@ -16,7 +16,6 @@ package org.eclipse.jetty.ee9.websocket.common;
import java.lang.invoke.MethodHandle;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
-import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.ee9.websocket.api.BatchMode;
@@ -82,7 +81,6 @@ public class JettyWebSocketFrameHandler implements FrameHandler
private WebSocketSession session;
private SuspendState state = SuspendState.DEMANDING;
private Runnable delayedOnFrame;
- private CoreSession coreSession;
public JettyWebSocketFrameHandler(WebSocketContainer container,
Object endpointInstance,
@@ -151,7 +149,6 @@ public class JettyWebSocketFrameHandler implements FrameHandler
try
{
customizer.customize(coreSession);
- this.coreSession = coreSession;
session = new WebSocketSession(container, coreSession, this);
if (!session.isOpen())
throw new IllegalStateException("Session is not open");
@@ -165,13 +162,11 @@ public class JettyWebSocketFrameHandler implements FrameHandler
pingHandle = InvokerUtils.bindTo(pingHandle, session);
pongHandle = InvokerUtils.bindTo(pongHandle, session);
- Executor executor = container.getExecutor();
-
if (textHandle != null)
- textSink = JettyWebSocketFrameHandlerFactory.createMessageSink(textHandle, textSinkClass, executor, session);
+ textSink = JettyWebSocketFrameHandlerFactory.createMessageSink(textHandle, textSinkClass, session);
if (binaryHandle != null)
- binarySink = JettyWebSocketFrameHandlerFactory.createMessageSink(binaryHandle, binarySinkClass, executor, session);
+ binarySink = JettyWebSocketFrameHandlerFactory.createMessageSink(binaryHandle, binarySinkClass, session);
if (openHandle != null)
openHandle.invoke();
@@ -191,7 +186,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
@Override
public void onFrame(Frame frame, Callback callback)
{
- try (AutoLock l = lock.lock())
+ try (AutoLock ignored = lock.lock())
{
switch (state)
{
@@ -227,26 +222,13 @@ public class JettyWebSocketFrameHandler implements FrameHandler
switch (frame.getOpCode())
{
- case OpCode.CLOSE:
- onCloseFrame(frame, callback);
- break;
- case OpCode.PING:
- onPingFrame(frame, callback);
- break;
- case OpCode.PONG:
- onPongFrame(frame, callback);
- break;
- case OpCode.TEXT:
- onTextFrame(frame, callback);
- break;
- case OpCode.BINARY:
- onBinaryFrame(frame, callback);
- break;
- case OpCode.CONTINUATION:
- onContinuationFrame(frame, callback);
- break;
- default:
- callback.failed(new IllegalStateException());
+ case OpCode.CLOSE -> onCloseFrame(frame, callback);
+ case OpCode.PING -> onPingFrame(frame, callback);
+ case OpCode.PONG -> onPongFrame(frame, callback);
+ case OpCode.TEXT -> onTextFrame(frame, callback);
+ case OpCode.BINARY -> onBinaryFrame(frame, callback);
+ case OpCode.CONTINUATION -> onContinuationFrame(frame, callback);
+ default -> callback.failed(new IllegalStateException());
}
}
@@ -283,7 +265,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
@Override
public void onClosed(CloseStatus closeStatus, Callback callback)
{
- try (AutoLock l = lock.lock())
+ try (AutoLock ignored = lock.lock())
{
// We are now closed and cannot suspend or resume.
state = SuspendState.CLOSED;
@@ -422,15 +404,9 @@ public class JettyWebSocketFrameHandler implements FrameHandler
acceptMessage(frame, callback);
}
- @Override
- public boolean isAutoDemanding()
- {
- return false;
- }
-
public void suspend()
{
- try (AutoLock l = lock.lock())
+ try (AutoLock ignored = lock.lock())
{
switch (state)
{
@@ -448,7 +424,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
{
boolean needDemand = false;
Runnable delayedFrame = null;
- try (AutoLock l = lock.lock())
+ try (AutoLock ignored = lock.lock())
{
switch (state)
{
@@ -485,7 +461,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
private void demand()
{
boolean demand = false;
- try (AutoLock l = lock.lock())
+ try (AutoLock ignored = lock.lock())
{
switch (state)
{
@@ -517,8 +493,8 @@ public class JettyWebSocketFrameHandler implements FrameHandler
if (cause instanceof BadPayloadException)
return new org.eclipse.jetty.ee9.websocket.api.exceptions.BadPayloadException(cause.getMessage(), cause);
- if (cause instanceof CloseException)
- return new org.eclipse.jetty.ee9.websocket.api.exceptions.CloseException(((CloseException)cause).getStatusCode(), cause.getMessage(), cause);
+ if (cause instanceof CloseException ce)
+ return new org.eclipse.jetty.ee9.websocket.api.exceptions.CloseException(ce.getStatusCode(), cause.getMessage(), cause);
if (cause instanceof WebSocketTimeoutException)
return new org.eclipse.jetty.ee9.websocket.api.exceptions.WebSocketTimeoutException(cause.getMessage(), cause);
@@ -526,11 +502,8 @@ public class JettyWebSocketFrameHandler implements FrameHandler
if (cause instanceof InvalidSignatureException)
return new org.eclipse.jetty.ee9.websocket.api.exceptions.InvalidWebSocketException(cause.getMessage(), cause);
- if (cause instanceof UpgradeException)
- {
- UpgradeException ue = (UpgradeException)cause;
+ if (cause instanceof UpgradeException ue)
return new org.eclipse.jetty.ee9.websocket.api.exceptions.UpgradeException(ue.getRequestURI(), ue.getResponseStatusCode(), cause);
- }
return cause;
}
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandlerFactory.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandlerFactory.java
index bc57346689d..51040f628a6 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandlerFactory.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandlerFactory.java
@@ -27,7 +27,6 @@ import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executor;
import org.eclipse.jetty.ee9.websocket.api.BatchMode;
import org.eclipse.jetty.ee9.websocket.api.Frame;
@@ -118,12 +117,6 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
new InvokerUtils.Arg(boolean.class).required()
};
- private static final InvokerUtils.Arg[] binaryPartialArrayCallingArgs = new InvokerUtils.Arg[]{
- new InvokerUtils.Arg(Session.class),
- new InvokerUtils.Arg(byte[].class).required(),
- new InvokerUtils.Arg(boolean.class).required()
- };
-
private final WebSocketContainer container;
private final WebSocketComponents components;
private final Map, JettyWebSocketFrameHandlerMetadata> metadataMap = new ConcurrentHashMap<>();
@@ -198,7 +191,7 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
metadata);
}
- public static MessageSink createMessageSink(MethodHandle msgHandle, Class extends MessageSink> sinkClass, Executor executor, WebSocketSession session)
+ public static MessageSink createMessageSink(MethodHandle msgHandle, Class extends MessageSink> sinkClass, WebSocketSession session)
{
if (msgHandle == null)
return null;
@@ -209,8 +202,8 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
{
MethodHandles.Lookup lookup = JettyWebSocketFrameHandlerFactory.getServerMethodHandleLookup();
MethodHandle ctorHandle = lookup.findConstructor(sinkClass,
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class));
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgHandle);
+ MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, boolean.class));
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgHandle, true);
}
catch (NoSuchMethodException e)
{
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/MessageInputStreamTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/MessageInputStreamTest.java
index c55a76e665a..be185eae542 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/MessageInputStreamTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/MessageInputStreamTest.java
@@ -25,6 +25,7 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.MessageInputStream;
@@ -43,7 +44,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
// Append a single message (simple, short)
Frame frame = new Frame(OpCode.TEXT);
@@ -64,7 +65,7 @@ public class MessageInputStreamTest
@Test
public void testMultipleReadsIntoSingleByteArray() throws IOException
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
// Append a single message (simple, short)
Frame frame = new Frame(OpCode.TEXT);
@@ -96,7 +97,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
final AtomicBoolean hadError = new AtomicBoolean(false);
final CountDownLatch startLatch = new CountDownLatch(1);
@@ -141,7 +142,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
final AtomicBoolean hadError = new AtomicBoolean(false);
@@ -176,7 +177,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
final AtomicBoolean hadError = new AtomicBoolean(false);
@@ -222,7 +223,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
// Append parts of message
Frame msg1 = new Frame(OpCode.BINARY).setPayload("Hello ").setFin(false);
@@ -249,7 +250,7 @@ public class MessageInputStreamTest
{
assertTimeout(Duration.ofMillis(5000), () ->
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
// Append parts of message
Frame msg1 = new Frame(OpCode.BINARY).setPayload("Hello ").setFin(false);
@@ -275,7 +276,7 @@ public class MessageInputStreamTest
@Test
public void testReadSingleByteIsNotSigned() throws Exception
{
- try (MessageInputStream stream = new MessageInputStream())
+ try (MessageInputStream stream = new MessageInputStream(new CoreSession.Empty()))
{
// Byte must be greater than 127.
int theByte = 200;
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/OutgoingMessageCapture.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/OutgoingMessageCapture.java
index 3852244e1f5..86689457b19 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/OutgoingMessageCapture.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/OutgoingMessageCapture.java
@@ -96,7 +96,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
String event = String.format("TEXT:fin=%b:len=%d", frame.isFin(), frame.getPayloadLength());
LOG.debug(event);
events.offer(event);
- messageSink = new StringMessageSink(this, wholeTextHandle);
+ messageSink = new StringMessageSink(this, wholeTextHandle, true);
break;
}
case OpCode.BINARY:
@@ -104,7 +104,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
String event = String.format("BINARY:fin=%b:len=%d", frame.isFin(), frame.getPayloadLength());
LOG.debug(event);
events.offer(event);
- messageSink = new ByteBufferMessageSink(this, wholeBinaryHandle);
+ messageSink = new ByteBufferMessageSink(this, wholeBinaryHandle, true);
break;
}
case OpCode.CONTINUATION:
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee9/websocket/tests/EventSocket.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee9/websocket/tests/EventSocket.java
index 3bb3ac44594..d4ca3bb5577 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee9/websocket/tests/EventSocket.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee9/websocket/tests/EventSocket.java
@@ -53,7 +53,7 @@ public class EventSocket
this.session = session;
behavior = session.getPolicy().getBehavior().name();
if (LOG.isDebugEnabled())
- LOG.debug("{} onOpen(): {}", toString(), session);
+ LOG.debug("{} onOpen(): {}", this, session);
openLatch.countDown();
}
@@ -61,7 +61,7 @@ public class EventSocket
public void onMessage(String message) throws IOException
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onMessage(): {}", toString(), message);
+ LOG.debug("{} onMessage(): {}", this, message);
textMessages.offer(message);
}
@@ -70,7 +70,7 @@ public class EventSocket
{
ByteBuffer message = ByteBuffer.wrap(buf, offset, len);
if (LOG.isDebugEnabled())
- LOG.debug("{} onMessage(): {}", toString(), message);
+ LOG.debug("{} onMessage(): {}", this, message);
binaryMessages.offer(message);
}
@@ -78,7 +78,7 @@ public class EventSocket
public void onClose(int statusCode, String reason)
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onClose(): {}:{}", toString(), statusCode, reason);
+ LOG.debug("{} onClose(): {}:{}", this, statusCode, reason);
this.closeCode = statusCode;
this.closeReason = reason;
closeLatch.countDown();
@@ -88,7 +88,7 @@ public class EventSocket
public void onError(Throwable cause)
{
if (LOG.isDebugEnabled())
- LOG.debug("{} onError(): {}", toString(), cause);
+ LOG.debug("{} onError()", this, cause);
error = cause;
errorLatch.countDown();
}