From c6b90e1abe25e993bba65b186cde431cb7e0c6a1 Mon Sep 17 00:00:00 2001 From: Nathan Callister Date: Mon, 21 Nov 2022 19:00:51 +1100 Subject: [PATCH 1/6] Added support for custom failure responses --- pom.xml | 4 +- .../org/java_websocket/WebSocketImpl.java | 42 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c72c92c65..2c2e885ef 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.java-websocket Java-WebSocket jar - 1.5.4-SNAPSHOT + 1.5.4.Ascom-SNAPSHOT Java-WebSocket A barebones WebSocket client and server implementation written 100% in Java https://github.com/TooTallNate/Java-WebSocket @@ -18,7 +18,7 @@ 20180813 - 4.3.1 + 6.3.1 3.1.1 3.7.0 1.6 diff --git a/src/main/java/org/java_websocket/WebSocketImpl.java b/src/main/java/org/java_websocket/WebSocketImpl.java index aad172127..f376d74bb 100644 --- a/src/main/java/org/java_websocket/WebSocketImpl.java +++ b/src/main/java/org/java_websocket/WebSocketImpl.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -301,6 +302,10 @@ private boolean decodeHandshake(ByteBuffer socketBufferNew) { closeConnectionDueToInternalServerError(e); return false; } + if (response.getHttpStatus() >= 400) { + closeConnectionDueToCustomFailure(response); + return false; + } write(d.createHandshake( d.postProcessHandshakeResponseAsServer(handshake, response))); draft = d; @@ -441,6 +446,43 @@ private void closeConnectionDueToInternalServerError(RuntimeException exception) write(generateHttpResponseDueToError(500)); flushAndClose(CloseFrame.NEVER_CONNECTED, exception.getMessage(), false); } + + /** + * Close the connection with a custom failure code and message. + * + * @param response The pre-filled response. + */ + private void closeConnectionDueToCustomFailure(ServerHandshakeBuilder response) { + write(generateCustomFailedHttpResponse(response)); + flushAndClose(CloseFrame.NEVER_CONNECTED, response.getHttpStatusMessage(), false); + } + + /** + * Create the response data for a custom failure message. + * + * @param response The pre-filled response + * @return The raw data to be sent + */ + private ByteBuffer generateCustomFailedHttpResponse(ServerHandshakeBuilder response) { + String responseContent = String.format( + "

%d %s

", + response.getHttpStatus(), + response.getHttpStatusMessage()); + + StringBuilder responseBuilder = new StringBuilder(); + responseBuilder.append("HTTP/1.1 ").append(response.getHttpStatus()).append("\r\n"); + responseBuilder.append("Content-Type: text/html\r\n"); + responseBuilder.append("Server: TooTallNate Java-WebSocket\r\n"); + responseBuilder.append("Content-Length: ").append(responseContent.length()).append("\r\n"); + for (Iterator iter = response.iterateHttpFields(); iter.hasNext(); ) { + String header = iter.next(); + responseBuilder.append(header).append(": ").append(response.getFieldValue(header)).append("\r\n"); + } + responseBuilder.append("\r\n"); + responseBuilder.append(responseContent); + return ByteBuffer.wrap( + Charsetfunctions.asciiBytes(responseBuilder.toString())); + } /** * Generate a simple response for the corresponding endpoint to indicate some error From ba7402d1874082d1242945fb308e6fd6c6cd2c74 Mon Sep 17 00:00:00 2001 From: Nathan Callister Date: Tue, 18 Apr 2023 21:29:05 +1000 Subject: [PATCH 2/6] Update version to 1.5.4.Ascom for release Note: This does not match any upstream release. When the upstream release occurs it must be marked as 1.5.4.Ascom.1 for our reference. DEV-1680 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 29a13eaa9..688d9c6bd 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.java-websocket Java-WebSocket jar - 1.5.4.Ascom-SNAPSHOT + 1.5.4.Ascom Java-WebSocket A barebones WebSocket client and server implementation written 100% in Java https://github.com/TooTallNate/Java-WebSocket From f18558e81f226f90610a21a25a4ba35bb43e4bca Mon Sep 17 00:00:00 2001 From: Nathan Callister Date: Tue, 18 Apr 2023 21:35:13 +1000 Subject: [PATCH 3/6] Update version to 1.5.1.Ascom.1-SNAPSHOT DEV-1680 --- pom.xml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 688d9c6bd..72759d996 100644 --- a/pom.xml +++ b/pom.xml @@ -1,14 +1,22 @@ + + + au.com.iwsoftware + iwsoftware + 3.0 + + 4.0.0 org.java-websocket Java-WebSocket jar - 1.5.4.Ascom - Java-WebSocket + 1.5.4.Ascom.1-SNAPSHOT + ${project.artifactId}-${project.version} A barebones WebSocket client and server implementation written 100% in Java https://github.com/TooTallNate/Java-WebSocket + UTF-8 2.0.6 @@ -30,8 +38,7 @@ org.java-websocket:Java-WebSocket marci4-github https://sonarcloud.io - 11 - 11 + 11 From 397117a1df12fb28cb121415ea94193581e209cc Mon Sep 17 00:00:00 2001 From: Nathan Callister Date: Mon, 17 Jun 2024 14:45:26 +1000 Subject: [PATCH 4/6] Fixed javadoc --- .../org/java_websocket/WebSocketAdapter.java | 2 +- .../org/java_websocket/WebSocketListener.java | 32 +++++++++---------- .../server/WebSocketServer.java | 12 +++---- .../java/org/java_websocket/util/Base64.java | 12 +++---- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/java_websocket/WebSocketAdapter.java b/src/main/java/org/java_websocket/WebSocketAdapter.java index e60215f8c..7fdf043d3 100644 --- a/src/main/java/org/java_websocket/WebSocketAdapter.java +++ b/src/main/java/org/java_websocket/WebSocketAdapter.java @@ -99,7 +99,7 @@ public void onWebsocketPong(WebSocket conn, Framedata f) { * Default implementation for onPreparePing, returns a (cached) PingFrame that has no application * data. * - * @param conn The WebSocket connection from which the ping frame will be sent. + * @param conn The {@code WebSocket} connection from which the ping frame will be sent. * @return PingFrame to be sent. * @see org.java_websocket.WebSocketListener#onPreparePing(WebSocket) */ diff --git a/src/main/java/org/java_websocket/WebSocketListener.java b/src/main/java/org/java_websocket/WebSocketListener.java index 6d2bfdd92..511f085e4 100644 --- a/src/main/java/org/java_websocket/WebSocketListener.java +++ b/src/main/java/org/java_websocket/WebSocketListener.java @@ -38,8 +38,8 @@ import org.java_websocket.handshake.ServerHandshakeBuilder; /** - * Implemented by WebSocketClient and WebSocketServer. The methods within are - * called by WebSocket. Almost every method takes a first parameter conn which represents + * Implemented by {@code WebSocketClient} and {@code WebSocketServer}. The methods within are + * called by {@code WebSocket}. Almost every method takes a first parameter conn which represents * the source of the respective event. */ public interface WebSocketListener { @@ -86,7 +86,7 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) /** * Called when an entire text frame has been received. Do whatever you want here... * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param message The UTF-8 decoded message that was received. */ void onWebsocketMessage(WebSocket conn, String message); @@ -94,7 +94,7 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) /** * Called when an entire binary frame has been received. Do whatever you want here... * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param blob The binary message that was received. */ void onWebsocketMessage(WebSocket conn, ByteBuffer blob); @@ -103,16 +103,16 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) * Called after onHandshakeReceived returns true. Indicates that a complete * WebSocket connection has been established, and we are ready to send/receive data. * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param d The handshake of the websocket instance */ void onWebsocketOpen(WebSocket conn, Handshakedata d); /** - * Called after WebSocket#close is explicity called, or when the other end of the + * Called after {@code WebSocket#close} is explicity called, or when the other end of the * WebSocket connection is closed. * - * @param ws The WebSocket instance this event is occurring on. + * @param ws The {@code WebSocket} instance this event is occurring on. * @param code The codes can be looked up here: {@link CloseFrame} * @param reason Additional information string * @param remote Returns whether or not the closing of the connection was initiated by the remote @@ -123,7 +123,7 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) /** * Called as soon as no further frames are accepted * - * @param ws The WebSocket instance this event is occurring on. + * @param ws The {@code WebSocket} instance this event is occurring on. * @param code The codes can be looked up here: {@link CloseFrame} * @param reason Additional information string * @param remote Returns whether or not the closing of the connection was initiated by the remote @@ -134,7 +134,7 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) /** * send when this peer sends a close handshake * - * @param ws The WebSocket instance this event is occurring on. + * @param ws The {@code WebSocket} instance this event is occurring on. * @param code The codes can be looked up here: {@link CloseFrame} * @param reason Additional information string */ @@ -144,7 +144,7 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) * Called if an exception worth noting occurred. If an error causes the connection to fail onClose * will be called additionally afterwards. * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param ex The exception that occurred.
Might be null if the exception is not related to * any specific connection. For example if the server port could not be bound. */ @@ -153,7 +153,7 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) /** * Called a ping frame has been received. This method must send a corresponding pong by itself. * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param f The ping frame. Control frames may contain payload. */ void onWebsocketPing(WebSocket conn, Framedata f); @@ -162,7 +162,7 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) * Called just before a ping frame is sent, in order to allow users to customize their ping frame * data. * - * @param conn The WebSocket connection from which the ping frame will be sent. + * @param conn The {@code WebSocket} connection from which the ping frame will be sent. * @return PingFrame to be sent. */ PingFrame onPreparePing(WebSocket conn); @@ -170,7 +170,7 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) /** * Called when a pong frame is received. * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param f The pong frame. Control frames may contain payload. **/ void onWebsocketPong(WebSocket conn, Framedata f); @@ -179,19 +179,19 @@ void onWebsocketHandshakeSentAsClient(WebSocket conn, ClientHandshake request) * This method is used to inform the selector thread that there is data queued to be written to * the socket. * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. */ void onWriteDemand(WebSocket conn); /** - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @return Returns the address of the endpoint this socket is bound to. * @see WebSocket#getLocalSocketAddress() */ InetSocketAddress getLocalSocketAddress(WebSocket conn); /** - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @return Returns the address of the endpoint this socket is connected to, or{@code null} if it * is unconnected. * @see WebSocket#getRemoteSocketAddress() diff --git a/src/main/java/org/java_websocket/server/WebSocketServer.java b/src/main/java/org/java_websocket/server/WebSocketServer.java index bb8178c25..dd4b36911 100644 --- a/src/main/java/org/java_websocket/server/WebSocketServer.java +++ b/src/main/java/org/java_websocket/server/WebSocketServer.java @@ -71,7 +71,7 @@ import org.slf4j.LoggerFactory; /** - * WebSocketServer is an abstract class that only takes care of the + * {@code WebSocketServer} is an abstract class that only takes care of the * HTTP handshake portion of WebSockets. It's up to a subclass to add functionality/purpose to the * server. */ @@ -183,7 +183,7 @@ public WebSocketServer(InetSocketAddress address, int decodercount, List /** * Creates a WebSocketServer that will attempt to bind/listen on the given address, and - * comply with Draft version draft. + * comply with {@code Draft} version draft. * * @param address The address (host:port) this server should listen on. * @param decodercount The number of {@link WebSocketWorker}s that will be used to process @@ -872,7 +872,7 @@ public InetSocketAddress getRemoteSocketAddress(WebSocket conn) { * Called after an opening handshake has been performed and the given websocket is ready to be * written on. * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param handshake The handshake of the websocket instance */ public abstract void onOpen(WebSocket conn, ClientHandshake handshake); @@ -880,7 +880,7 @@ public InetSocketAddress getRemoteSocketAddress(WebSocket conn) { /** * Called after the websocket connection has been closed. * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param code The codes can be looked up here: {@link CloseFrame} * @param reason Additional information string * @param remote Returns whether or not the closing of the connection was initiated by the remote @@ -891,7 +891,7 @@ public InetSocketAddress getRemoteSocketAddress(WebSocket conn) { /** * Callback for string messages received from the remote host * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param message The UTF-8 decoded message that was received. * @see #onMessage(WebSocket, ByteBuffer) **/ @@ -919,7 +919,7 @@ public InetSocketAddress getRemoteSocketAddress(WebSocket conn) { /** * Callback for binary messages received from the remote host * - * @param conn The WebSocket instance this event is occurring on. + * @param conn The {@code WebSocket} instance this event is occurring on. * @param message The binary message that was received. * @see #onMessage(WebSocket, ByteBuffer) **/ diff --git a/src/main/java/org/java_websocket/util/Base64.java b/src/main/java/org/java_websocket/util/Base64.java index e9ff7b87a..6839836d4 100644 --- a/src/main/java/org/java_websocket/util/Base64.java +++ b/src/main/java/org/java_websocket/util/Base64.java @@ -35,7 +35,7 @@ *
* byte[] myByteArray = Base64.decode( encoded ); * - *

The options parameter, which appears in a few places, is used to pass + *

The {@code options} parameter, which appears in a few places, is used to pass * several pieces of information to the encoder. In the "higher level" methods such as encodeBytes( * bytes, options ) the options parameter can be used to indicate such things as first gzipping the * bytes before encoding them, not inserting linefeeds, and encoding using the URL-safe and Ordered @@ -140,9 +140,9 @@ * when data that's being decoded is gzip-compressed and will decompress it * automatically. Generally things are cleaner. You'll probably have to * change some method calls that you were making to support the new - * options format (ints that you "OR" together). + * options format ({@code int}s that you "OR" together). *

  • v1.5.1 - Fixed bug when decompressing and decoding to a - * byte[] using decode( String s, boolean gzipCompressed ). + * byte[] using {@code decode( String s, boolean gzipCompressed )}. * Added the ability to "suspend" encoding in the Output Stream so * you can turn on and off the encoding if you need to embed base64 * data in an otherwise "normal" stream (like an XML file).
  • @@ -873,7 +873,7 @@ else if (source[srcOffset + 3] == EQUALS_SIGN) { /** * A {@link Base64.OutputStream} will write data to another - * java.io.OutputStream, given in the constructor, + * {@code java.io.OutputStream}, given in the constructor, * and encode/decode to/from Base64 notation on the fly. * * @see Base64 @@ -895,7 +895,7 @@ public static class OutputStream extends java.io.FilterOutputStream { /** * Constructs a {@link Base64.OutputStream} in ENCODE mode. * - * @param out the java.io.OutputStream to which data will be written. + * @param out the {@code java.io.OutputStream} to which data will be written. * @since 1.3 */ public OutputStream(java.io.OutputStream out) { @@ -914,7 +914,7 @@ public OutputStream(java.io.OutputStream out) { *

    * Example: new Base64.OutputStream( out, Base64.ENCODE ) * - * @param out the java.io.OutputStream to which data will be written. + * @param out the {@code java.io.OutputStream} to which data will be written. * @param options Specified options. * @see Base64#ENCODE * @see Base64#DO_BREAK_LINES From 51c17455b0a06e2fab183b8977a5f953323b6edf Mon Sep 17 00:00:00 2001 From: Nathan Callister Date: Mon, 17 Jun 2024 16:05:14 +1000 Subject: [PATCH 5/6] Update parent POM --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c2048ecd9..2679aa4b9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ au.com.iwsoftware iwsoftware - 3.0 + 3.4 4.0.0 From 8624e35ddf20e6fbab2093f33c259a351944e68f Mon Sep 17 00:00:00 2001 From: Nathan Callister Date: Mon, 17 Jun 2024 16:13:34 +1000 Subject: [PATCH 6/6] Added timeout to Issue941Test --- src/test/java/org/java_websocket/issues/Issue941Test.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/java_websocket/issues/Issue941Test.java b/src/test/java/org/java_websocket/issues/Issue941Test.java index a9aedbaef..3c678eb5b 100644 --- a/src/test/java/org/java_websocket/issues/Issue941Test.java +++ b/src/test/java/org/java_websocket/issues/Issue941Test.java @@ -25,8 +25,6 @@ package org.java_websocket.issues; -import static org.junit.Assert.assertArrayEquals; - import java.net.InetSocketAddress; import java.net.URI; import java.nio.ByteBuffer; @@ -39,6 +37,7 @@ import org.java_websocket.handshake.ServerHandshake; import org.java_websocket.server.WebSocketServer; import org.java_websocket.util.SocketUtil; +import static org.junit.Assert.assertArrayEquals; import org.junit.Test; public class Issue941Test { @@ -47,7 +46,7 @@ public class Issue941Test { private CountDownLatch pongLatch = new CountDownLatch(1); private byte[] pingBuffer, receivedPingBuffer, pongBuffer; - @Test + @Test(timeout = 10000) public void testIssue() throws Exception { int port = SocketUtil.getAvailablePort(); WebSocketClient client = new WebSocketClient(new URI("ws://localhost:" + port)) {