Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/qz/ws/PrintSocketClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.*;


@WebSocket
Expand All @@ -66,7 +65,11 @@ public void onConnect(Session session) {
trayManager.displayInfoMessage("Client connected");

//new connections are unknown until they send a proper certificate
openConnections.put(((InetSocketAddress)session.getRemoteAddress()).getPort(), new SocketConnection(Certificate.UNKNOWN));
SocketConnection connection = new SocketConnection(Certificate.UNKNOWN);
openConnections.put(((InetSocketAddress)session.getRemoteAddress()).getPort(), connection);

//Browsers now slow or interrupt JS timers, leading to the websockets keepalive failing. A server-side keepalive ping will qct as a fallback.
connection.startKeepAlive(session, (int)(session.getPolicy().getIdleTimeout().toSeconds() / 2));
}

@OnWebSocketClose
Expand Down
30 changes: 30 additions & 0 deletions src/qz/ws/SocketConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jssc.SerialPortException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.jetty.websocket.api.Session;
import qz.auth.Certificate;
import qz.communication.*;
import qz.printer.status.StatusMonitor;
Expand All @@ -11,6 +12,10 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class SocketConnection {

Expand All @@ -32,6 +37,9 @@ public class SocketConnection {
// DeviceOptions -> open DeviceIO
private final HashMap<DeviceOptions,DeviceIO> openDevices = new HashMap<>();

private static final ScheduledExecutorService keepAliveExecutor = Executors.newScheduledThreadPool(1);
private ScheduledFuture<?> keepAlive;


public SocketConnection(Certificate cert) {
certificate = cert;
Expand Down Expand Up @@ -95,6 +103,27 @@ public FileIO getFileListener(Path absolute) {
return openFiles.get(absolute);
}

public void startKeepAlive(Session session, int seconds) {
if (keepAlive != null && (!keepAlive.isCancelled() || !keepAlive.isDone())) {
stopKeepAlive();
}
//Sane fallback, this should never come up.
seconds = Math.max(seconds, 15);
keepAlive = keepAliveExecutor.scheduleAtFixedRate(() -> {
try {
session.getRemote().sendPing(null);
}
catch(IOException e) {
log.warn("Websocket keepalive failed. Stopping", e);
this.stopKeepAlive();
}
}, 0, seconds, TimeUnit.SECONDS);
}

public void stopKeepAlive() {
keepAlive.cancel(true);
}

public void removeFileListener(Path absolute) {
openFiles.remove(absolute);
}
Expand Down Expand Up @@ -147,6 +176,7 @@ public synchronized void disconnect() throws SerialPortException, DeviceExceptio
dio.close();
}

stopKeepAlive();
removeAllFileListeners();
stopDeviceListening();
StatusMonitor.stopListening(this);
Expand Down
Loading