Skip to content

Commit 1a790f8

Browse files
sunweiyangfacebook-github-bot
authored andcommitted
Use ConcurrentHashMap for handling concurrent Android websockets, and…
Summary: … prevent unknown websocket IDs from crashing on Android (show warning on development builds instead) This PR addresses #3346; an unknown websocket ID should produce a warning during development, but not cause crashes in production RN apps. This PR was created by satya164's request, and was inspired by tanthanh289's suggestion on #3346's thread. On Android, create a websocket using a service like Pusher (`pusher-js` npm package) or manually, and then induce removal of its websocket ID. Result should be a red warning screen during development, and no crash in the app's release variant. [ANDROID] [BUGFIX] [WebSocket] - Prevent unknown websocket IDs from crashing on Android Closes #17884 Differential Revision: D6954038 Pulled By: hramos fbshipit-source-id: b346d80d7568996b8819c0de54552abb534cbfae
1 parent 01a58d1 commit 1a790f8

File tree

1 file changed

+55
-10
lines changed

1 file changed

+55
-10
lines changed

ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java

+55-10
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.io.IOException;
2828
import java.net.URI;
2929
import java.net.URISyntaxException;
30+
import java.util.concurrent.ConcurrentHashMap;
3031
import java.util.HashMap;
3132
import java.util.List;
3233
import java.util.Map;
@@ -48,8 +49,8 @@ public interface ContentHandler {
4849
void onMessage(ByteString byteString, WritableMap params);
4950
}
5051

51-
private final Map<Integer, WebSocket> mWebSocketConnections = new HashMap<>();
52-
private final Map<Integer, ContentHandler> mContentHandlers = new HashMap<>();
52+
private final Map<Integer, WebSocket> mWebSocketConnections = new ConcurrentHashMap<>();
53+
private final Map<Integer, ContentHandler> mContentHandlers = new ConcurrentHashMap<>();
5354

5455
private ReactContext mReactContext;
5556
private ForwardingCookieHandler mCookieHandler;
@@ -224,8 +225,19 @@ public void close(int code, String reason, int id) {
224225
public void send(String message, int id) {
225226
WebSocket client = mWebSocketConnections.get(id);
226227
if (client == null) {
227-
// This is a programmer error
228-
throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id);
228+
// This is a programmer error -- display development warning
229+
WritableMap params = Arguments.createMap();
230+
params.putInt("id", id);
231+
params.putString("message", "client is null");
232+
sendEvent("websocketFailed", params);
233+
params = Arguments.createMap();
234+
params.putInt("id", id);
235+
params.putInt("code", 0);
236+
params.putString("reason", "client is null");
237+
sendEvent("websocketClosed", params);
238+
mWebSocketConnections.remove(id);
239+
mContentHandlers.remove(id);
240+
return;
229241
}
230242
try {
231243
client.send(message);
@@ -238,8 +250,19 @@ public void send(String message, int id) {
238250
public void sendBinary(String base64String, int id) {
239251
WebSocket client = mWebSocketConnections.get(id);
240252
if (client == null) {
241-
// This is a programmer error
242-
throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id);
253+
// This is a programmer error -- display development warning
254+
WritableMap params = Arguments.createMap();
255+
params.putInt("id", id);
256+
params.putString("message", "client is null");
257+
sendEvent("websocketFailed", params);
258+
params = Arguments.createMap();
259+
params.putInt("id", id);
260+
params.putInt("code", 0);
261+
params.putString("reason", "client is null");
262+
sendEvent("websocketClosed", params);
263+
mWebSocketConnections.remove(id);
264+
mContentHandlers.remove(id);
265+
return;
243266
}
244267
try {
245268
client.send(ByteString.decodeBase64(base64String));
@@ -251,8 +274,19 @@ public void sendBinary(String base64String, int id) {
251274
public void sendBinary(ByteString byteString, int id) {
252275
WebSocket client = mWebSocketConnections.get(id);
253276
if (client == null) {
254-
// This is a programmer error
255-
throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id);
277+
// This is a programmer error -- display development warning
278+
WritableMap params = Arguments.createMap();
279+
params.putInt("id", id);
280+
params.putString("message", "client is null");
281+
sendEvent("websocketFailed", params);
282+
params = Arguments.createMap();
283+
params.putInt("id", id);
284+
params.putInt("code", 0);
285+
params.putString("reason", "client is null");
286+
sendEvent("websocketClosed", params);
287+
mWebSocketConnections.remove(id);
288+
mContentHandlers.remove(id);
289+
return;
256290
}
257291
try {
258292
client.send(byteString);
@@ -265,8 +299,19 @@ public void sendBinary(ByteString byteString, int id) {
265299
public void ping(int id) {
266300
WebSocket client = mWebSocketConnections.get(id);
267301
if (client == null) {
268-
// This is a programmer error
269-
throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id);
302+
// This is a programmer error -- display development warning
303+
WritableMap params = Arguments.createMap();
304+
params.putInt("id", id);
305+
params.putString("message", "client is null");
306+
sendEvent("websocketFailed", params);
307+
params = Arguments.createMap();
308+
params.putInt("id", id);
309+
params.putInt("code", 0);
310+
params.putString("reason", "client is null");
311+
sendEvent("websocketClosed", params);
312+
mWebSocketConnections.remove(id);
313+
mContentHandlers.remove(id);
314+
return;
270315
}
271316
try {
272317
client.send(ByteString.EMPTY);

0 commit comments

Comments
 (0)