From ad2f24fe3a78f5b9107d9e7ab0e190ef7978cd06 Mon Sep 17 00:00:00 2001 From: Wei Sun <sunw@alum.mit.edu> Date: Tue, 6 Feb 2018 17:11:16 -0800 Subject: [PATCH] Use ConcurrentHashMap for handling concurrent Android websockets, and prevent unknown websocket IDs from crashing on Android (show warning on development builds instead) --- .../modules/websocket/WebSocketModule.java | 65 ++++++++++++++++--- 1 file changed, 55 insertions(+), 10 deletions(-) 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 2bfae94e7a9428..c7b6c8bbe50d79 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 @@ -27,6 +27,7 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.util.concurrent.ConcurrentHashMap; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -48,8 +49,8 @@ public interface ContentHandler { void onMessage(ByteString byteString, WritableMap params); } - private final Map<Integer, WebSocket> mWebSocketConnections = new HashMap<>(); - private final Map<Integer, ContentHandler> mContentHandlers = new HashMap<>(); + private final Map<Integer, WebSocket> mWebSocketConnections = new ConcurrentHashMap<>(); + private final Map<Integer, ContentHandler> mContentHandlers = new ConcurrentHashMap<>(); private ReactContext mReactContext; private ForwardingCookieHandler mCookieHandler; @@ -224,8 +225,19 @@ public void close(int code, String reason, int id) { public void send(String message, 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); + // This is a programmer error -- display development warning + WritableMap params = Arguments.createMap(); + params.putInt("id", id); + params.putString("message", "client is null"); + sendEvent("websocketFailed", params); + params = Arguments.createMap(); + params.putInt("id", id); + params.putInt("code", 0); + params.putString("reason", "client is null"); + sendEvent("websocketClosed", params); + mWebSocketConnections.remove(id); + mContentHandlers.remove(id); + return; } try { client.send(message); @@ -238,8 +250,19 @@ public void send(String message, int id) { public void sendBinary(String base64String, 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); + // This is a programmer error -- display development warning + WritableMap params = Arguments.createMap(); + params.putInt("id", id); + params.putString("message", "client is null"); + sendEvent("websocketFailed", params); + params = Arguments.createMap(); + params.putInt("id", id); + params.putInt("code", 0); + params.putString("reason", "client is null"); + sendEvent("websocketClosed", params); + mWebSocketConnections.remove(id); + mContentHandlers.remove(id); + return; } try { client.send(ByteString.decodeBase64(base64String)); @@ -251,8 +274,19 @@ public void sendBinary(String base64String, int id) { public void sendBinary(ByteString byteString, 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); + // This is a programmer error -- display development warning + WritableMap params = Arguments.createMap(); + params.putInt("id", id); + params.putString("message", "client is null"); + sendEvent("websocketFailed", params); + params = Arguments.createMap(); + params.putInt("id", id); + params.putInt("code", 0); + params.putString("reason", "client is null"); + sendEvent("websocketClosed", params); + mWebSocketConnections.remove(id); + mContentHandlers.remove(id); + return; } try { client.send(byteString); @@ -265,8 +299,19 @@ public void sendBinary(ByteString byteString, int id) { 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); + // This is a programmer error -- display development warning + WritableMap params = Arguments.createMap(); + params.putInt("id", id); + params.putString("message", "client is null"); + sendEvent("websocketFailed", params); + params = Arguments.createMap(); + params.putInt("id", id); + params.putInt("code", 0); + params.putString("reason", "client is null"); + sendEvent("websocketClosed", params); + mWebSocketConnections.remove(id); + mContentHandlers.remove(id); + return; } try { client.send(ByteString.EMPTY);