Skip to content

Commit 89df856

Browse files
authored
Add ability to customize ping messages with custom data, see iss… (TooTallNate#944)
Add ability to customize ping messages with custom data, see issue#941
2 parents 6230be5 + d64295e commit 89df856

4 files changed

Lines changed: 135 additions & 10 deletions

File tree

‎src/main/java/org/java_websocket/WebSocketAdapter.java‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
**/
4141
public abstract class WebSocketAdapter implements WebSocketListener {
4242

43+
private PingFrame pingFrame;
44+
4345
/**
4446
* This default implementation does not do anything. Go ahead and overwrite it.
4547
*
@@ -85,4 +87,18 @@ public void onWebsocketPing( WebSocket conn, Framedata f ) {
8587
public void onWebsocketPong( WebSocket conn, Framedata f ) {
8688
//To overwrite
8789
}
90+
91+
/**
92+
* Default implementation for onPreparePing, returns a (cached) PingFrame that has no application data.
93+
* @see org.java_websocket.WebSocketListener#onPreparePing(WebSocket)
94+
*
95+
* @param conn The <tt>WebSocket</tt> connection from which the ping frame will be sent.
96+
* @return PingFrame to be sent.
97+
*/
98+
@Override
99+
public PingFrame onPreparePing(WebSocket conn) {
100+
if(pingFrame == null)
101+
pingFrame = new PingFrame();
102+
return pingFrame;
103+
}
88104
}

‎src/main/java/org/java_websocket/WebSocketImpl.java‎

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,6 @@ public class WebSocketImpl implements WebSocket {
161161
*/
162162
private final Object synchronizeWriteObject = new Object();
163163

164-
/**
165-
* Attribute to cache a ping frame
166-
*/
167-
private PingFrame pingFrame;
168-
169164
/**
170165
* Attribute to store connection attachment
171166
* @since 1.3.7
@@ -658,11 +653,12 @@ public void sendFrame( Framedata framedata ) {
658653
send( Collections.singletonList( framedata ) );
659654
}
660655

661-
public void sendPing() {
662-
if( pingFrame == null ) {
663-
pingFrame = new PingFrame();
664-
}
665-
sendFrame( pingFrame );
656+
public void sendPing() throws NullPointerException {
657+
// Gets a PingFrame from WebSocketListener(wsl) and sends it.
658+
PingFrame pingFrame = wsl.onPreparePing(this);
659+
if(pingFrame == null)
660+
throw new NullPointerException("onPreparePing(WebSocket) returned null. PingFrame to sent can't be null.");
661+
sendFrame(pingFrame);
666662
}
667663

668664
@Override

‎src/main/java/org/java_websocket/WebSocketListener.java‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.java_websocket.exceptions.InvalidDataException;
3333
import org.java_websocket.framing.CloseFrame;
3434
import org.java_websocket.framing.Framedata;
35+
import org.java_websocket.framing.PingFrame;
3536
import org.java_websocket.handshake.ClientHandshake;
3637
import org.java_websocket.handshake.Handshakedata;
3738
import org.java_websocket.handshake.ServerHandshake;
@@ -169,6 +170,14 @@ public interface WebSocketListener {
169170
*/
170171
void onWebsocketPing( WebSocket conn, Framedata f );
171172

173+
/**
174+
* Called just before a ping frame is sent, in order to allow users to customize their ping frame data.
175+
*
176+
* @param conn The <tt>WebSocket</tt> connection from which the ping frame will be sent.
177+
* @return PingFrame to be sent.
178+
*/
179+
PingFrame onPreparePing(WebSocket conn );
180+
172181
/**
173182
* Called when a pong frame is received.
174183
*
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2010-2019 Nathan Rajlich
3+
*
4+
* Permission is hereby granted, free of charge, to any person
5+
* obtaining a copy of this software and associated documentation
6+
* files (the "Software"), to deal in the Software without
7+
* restriction, including without limitation the rights to use,
8+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following
11+
* conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
* OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
package org.java_websocket.issues;
27+
28+
import org.java_websocket.WebSocket;
29+
import org.java_websocket.client.WebSocketClient;
30+
import org.java_websocket.framing.Framedata;
31+
import org.java_websocket.framing.PingFrame;
32+
import org.java_websocket.handshake.ClientHandshake;
33+
import org.java_websocket.handshake.ServerHandshake;
34+
import org.java_websocket.server.WebSocketServer;
35+
import org.java_websocket.util.SocketUtil;
36+
import org.junit.Test;
37+
38+
import java.net.InetSocketAddress;
39+
import java.net.URI;
40+
import java.nio.ByteBuffer;
41+
import java.util.concurrent.CountDownLatch;
42+
43+
import static org.junit.Assert.assertArrayEquals;
44+
45+
public class Issue941Test {
46+
47+
private CountDownLatch pingLatch = new CountDownLatch(1);
48+
private CountDownLatch pongLatch = new CountDownLatch(1);
49+
private byte[] pingBuffer, receivedPingBuffer, pongBuffer;
50+
51+
@Test
52+
public void testIssue() throws Exception {
53+
int port = SocketUtil.getAvailablePort();
54+
WebSocketClient client = new WebSocketClient(new URI( "ws://localhost:" + port)) {
55+
@Override
56+
public void onOpen(ServerHandshake handshakedata) { }
57+
@Override
58+
public void onMessage(String message) { }
59+
@Override
60+
public void onClose(int code, String reason, boolean remote) { }
61+
@Override
62+
public void onError(Exception ex) { }
63+
@Override
64+
public PingFrame onPreparePing(WebSocket conn) {
65+
PingFrame frame = new PingFrame();
66+
pingBuffer = new byte[]{1,2,3,4,5,6,7,8,9,10};
67+
frame.setPayload(ByteBuffer.wrap(pingBuffer));
68+
return frame;
69+
}
70+
@Override
71+
public void onWebsocketPong(WebSocket conn, Framedata f) {
72+
pongBuffer = f.getPayloadData().array();
73+
pongLatch.countDown();
74+
}
75+
};
76+
77+
WebSocketServer server = new WebSocketServer(new InetSocketAddress(port)) {
78+
@Override
79+
public void onOpen(WebSocket conn, ClientHandshake handshake) { }
80+
@Override
81+
public void onClose(WebSocket conn, int code, String reason, boolean remote) { }
82+
@Override
83+
public void onMessage(WebSocket conn, String message) { }
84+
@Override
85+
public void onError(WebSocket conn, Exception ex) { }
86+
@Override
87+
public void onStart() { }
88+
@Override
89+
public void onWebsocketPing(WebSocket conn, Framedata f) {
90+
receivedPingBuffer = f.getPayloadData().array();
91+
super.onWebsocketPing(conn, f);
92+
pingLatch.countDown();
93+
}
94+
};
95+
96+
server.start();
97+
client.connectBlocking();
98+
client.setConnectionLostTimeout(1);
99+
pingLatch.await();
100+
assertArrayEquals(pingBuffer, receivedPingBuffer);
101+
pongLatch.await();
102+
assertArrayEquals(pingBuffer, pongBuffer);
103+
}
104+
}

0 commit comments

Comments
 (0)