From a3ffa7a71e5128793c879f969ef2225d17acf93a Mon Sep 17 00:00:00 2001 From: 0xb00bface <0xboobface@gmail.com> Date: Sat, 19 Dec 2020 17:41:44 +0100 Subject: [PATCH] Improve error handling and set timeouts in the Cam4 websocket --- .../java/ctbrec/sites/cam4/Cam4Model.java | 4 +++ .../java/ctbrec/sites/cam4/Cam4WsClient.java | 27 ++++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java b/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java index 953cb2ac..f84f242d 100644 --- a/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java +++ b/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java @@ -87,9 +87,13 @@ public class Cam4Model extends AbstractModel { case "INSIDE_PS": onlineState = PRIVATE; break; + case "INSIDE_GS": case "GROUP_SHOW": onlineState = GROUP; break; + case "PAUSED": + onlineState = AWAY; + break; case "OFFLINE": onlineState = OFFLINE; break; diff --git a/common/src/main/java/ctbrec/sites/cam4/Cam4WsClient.java b/common/src/main/java/ctbrec/sites/cam4/Cam4WsClient.java index 81a5c9a7..e5a9557b 100644 --- a/common/src/main/java/ctbrec/sites/cam4/Cam4WsClient.java +++ b/common/src/main/java/ctbrec/sites/cam4/Cam4WsClient.java @@ -2,6 +2,7 @@ package ctbrec.sites.cam4; import static ctbrec.io.HttpConstants.*; +import java.io.EOFException; import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -34,7 +35,8 @@ public class Cam4WsClient { private String token; private WebSocket websocket; private int r = 1; - private Map> responseFutures = new HashMap<>(); + private Map> responseFuturesByPath = new HashMap<>(); + private Map> responseFuturesBySequence = new HashMap<>(); public Cam4WsClient(Config config, Cam4 site, Cam4Model model) { this.config = config; @@ -55,7 +57,7 @@ public class Cam4WsClient { String p = "chatRooms/" + model.getName() + "/roomState"; CompletableFuture roomStateFuture = send(p, "{\"t\":\"d\",\"d\":{\"r\":" + (r++) + ",\"a\":\"q\",\"b\":{\"p\":\"" + p + "\",\"h\":\"\"}}}"); try { - JSONObject roomState = parseRoomStateResponse(roomStateFuture.get(5000, TimeUnit.SECONDS)); + JSONObject roomState = parseRoomStateResponse(roomStateFuture.get(1, TimeUnit.SECONDS)); websocket.close(1000, ""); return roomState; } catch (InterruptedException e) { @@ -69,7 +71,7 @@ public class Cam4WsClient { private boolean connectAndAuthorize() throws IOException { CompletableFuture connectedAndAuthorized = openWebsocketConnection(); try { - return connectedAndAuthorized.get(5000, TimeUnit.SECONDS); + return connectedAndAuthorized.get(1, TimeUnit.SECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IOException("Interrupted while connecting with websocket"); @@ -85,7 +87,7 @@ public class Cam4WsClient { if (!sent) { future.completeExceptionally(new IOException("send() returned false")); } else { - responseFutures.put(p, future); + responseFuturesByPath.put(p, future); } return future; } @@ -157,6 +159,9 @@ public class Cam4WsClient { public void onFailure(WebSocket webSocket, Throwable t, Response response) { super.onFailure(webSocket, t, response); try { + if (t instanceof EOFException) { + return; + } if(response != null) { LOG.error("failure {}: {}", model, response.body().string(), t); } else { @@ -164,8 +169,9 @@ public class Cam4WsClient { } } catch (IOException e) { LOG.error("Connection failure and couldn't get the response body", e); + } finally { + connectedAndAuthorized.completeExceptionally(t); } - connectedAndAuthorized.completeExceptionally(t); } @Override @@ -180,11 +186,18 @@ public class Cam4WsClient { JSONObject body = d.getJSONObject("b"); String status = body.optString("s"); connectedAndAuthorized.complete(status.equals("ok")); + } else if (responseFuturesBySequence.containsKey(responseSequence)) { + JSONObject body = d.getJSONObject("b"); + String status = body.optString("s"); + if (!status.equals("ok")) { + CompletableFuture future = responseFuturesBySequence.remove(responseSequence); + future.completeExceptionally(new IOException(status)); + } } else if (d.has("b")) { JSONObject body = d.getJSONObject("b"); String p = body.optString("p", "-"); - if (responseFutures.containsKey(p)) { - CompletableFuture future = responseFutures.get(p); + if (responseFuturesByPath.containsKey(p)) { + CompletableFuture future = responseFuturesByPath.remove(p); future.complete(text); } }