From 4ac4f86bf5fa7449434b942d826dd3a13bb9e7d3 Mon Sep 17 00:00:00 2001 From: danielbasedow Date: Tue, 5 Jul 2016 05:52:24 -0700 Subject: [PATCH] Add ping to WebSocket Summary: Idle WebSocket connections get reset after a few minutes of inactivity. To prevent this, most WebSocket implementations offer sending special ping messages. This PR adds a method `sendPing()` to WebSocket. Ping payloads are not supported. Manual testing can be done by adding `connection.on('ping', _ => console.log('Received ping'));` to a ws connection or using a packet sniffer while sending pings. Closes https://github.com/facebook/react-native/pull/8505 Differential Revision: D3516260 Pulled By: dmmiller fbshipit-source-id: cfebf5899188ae53254d5be6b666a9075e0eed89 --- Libraries/WebSocket/RCTWebSocketModule.m | 5 +++++ Libraries/WebSocket/WebSocket.js | 8 ++++++++ .../react/modules/websocket/WebSocketModule.java | 15 +++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/Libraries/WebSocket/RCTWebSocketModule.m b/Libraries/WebSocket/RCTWebSocketModule.m index d83e5942b..6a914a6f4 100644 --- a/Libraries/WebSocket/RCTWebSocketModule.m +++ b/Libraries/WebSocket/RCTWebSocketModule.m @@ -77,6 +77,11 @@ RCT_EXPORT_METHOD(sendBinary:(NSString *)base64String socketID:(nonnull NSNumber [_sockets[socketID] send:message]; } +RCT_EXPORT_METHOD(ping:(nonnull NSNumber *)socketID) +{ + [_sockets[socketID] sendPing:NULL]; +} + RCT_EXPORT_METHOD(close:(nonnull NSNumber *)socketID) { [_sockets[socketID] close]; diff --git a/Libraries/WebSocket/WebSocket.js b/Libraries/WebSocket/WebSocket.js index f5063fdb2..16f2866ca 100644 --- a/Libraries/WebSocket/WebSocket.js +++ b/Libraries/WebSocket/WebSocket.js @@ -135,6 +135,14 @@ class WebSocket extends EventTarget(...WEBSOCKET_EVENTS) { throw new Error('Unsupported data type'); } + ping(): void { + if (this.readyState === this.CONNECTING) { + throw new Error('INVALID_STATE_ERR'); + } + + RCTWebSocketModule.ping(this._socketId); + } + _close(code?: number, reason?: string): void { if (Platform.OS === 'android') { // See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java index 5f318cab6..5e3686a73 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java @@ -229,6 +229,21 @@ public class WebSocketModule extends ReactContextBaseJavaModule { } } + @ReactMethod + public void ping(int id) { + WebSocket client = mWebSocketConnections.get(id); + if (client == null) { + // This is a programmer error + throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id); + } + try { + Buffer buffer = new Buffer(); + client.sendPing(buffer); + } catch (IOException | IllegalStateException e) { + notifyWebSocketFailed(id, e.getMessage()); + } + } + private void notifyWebSocketFailed(int id, String message) { WritableMap params = Arguments.createMap(); params.putInt("id", id);