Change websocket keepalive response time to 20s.
This commit is contained in:
parent
47673be4e0
commit
f579b79d2e
2 changed files with 43 additions and 15 deletions
|
@ -30,8 +30,16 @@ public final class SignalWebSocketHealthMonitor implements HealthMonitor {
|
||||||
|
|
||||||
private static final String TAG = Log.tag(SignalWebSocketHealthMonitor.class);
|
private static final String TAG = Log.tag(SignalWebSocketHealthMonitor.class);
|
||||||
|
|
||||||
private static final long KEEP_ALIVE_SEND_CADENCE = TimeUnit.SECONDS.toMillis(WebSocketConnection.KEEPALIVE_TIMEOUT_SECONDS);
|
/**
|
||||||
private static final long MAX_TIME_SINCE_SUCCESSFUL_KEEP_ALIVE = KEEP_ALIVE_SEND_CADENCE * 3;
|
* This is the amount of time in between sent keep alives. Must be greater than {@link SignalWebSocketHealthMonitor#KEEP_ALIVE_TIMEOUT}
|
||||||
|
*/
|
||||||
|
private static final long KEEP_ALIVE_SEND_CADENCE = TimeUnit.SECONDS.toMillis(WebSocketConnection.KEEPALIVE_FREQUENCY_SECONDS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the amount of time we will wait for a response to the keep alive before we consider the websockets dead.
|
||||||
|
* It is required that this value be less than {@link SignalWebSocketHealthMonitor#KEEP_ALIVE_SEND_CADENCE}
|
||||||
|
*/
|
||||||
|
private static final long KEEP_ALIVE_TIMEOUT = TimeUnit.SECONDS.toMillis(20);
|
||||||
|
|
||||||
private final Executor executor = Executors.newSingleThreadExecutor();
|
private final Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
@ -103,11 +111,12 @@ public final class SignalWebSocketHealthMonitor implements HealthMonitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onKeepAliveResponse(long sentTimestamp, boolean isIdentifiedWebSocket) {
|
public void onKeepAliveResponse(long sentTimestamp, boolean isIdentifiedWebSocket) {
|
||||||
|
final long keepAliveTime = System.currentTimeMillis();
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
if (isIdentifiedWebSocket) {
|
if (isIdentifiedWebSocket) {
|
||||||
identified.lastKeepAliveReceived = System.currentTimeMillis();
|
identified.lastKeepAliveReceived = keepAliveTime;
|
||||||
} else {
|
} else {
|
||||||
unidentified.lastKeepAliveReceived = System.currentTimeMillis();
|
unidentified.lastKeepAliveReceived = keepAliveTime;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -138,7 +147,7 @@ public final class SignalWebSocketHealthMonitor implements HealthMonitor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends periodic heartbeats/keep-alives over both WebSockets to prevent connection timeouts. If
|
* Sends periodic heartbeats/keep-alives over both WebSockets to prevent connection timeouts. If
|
||||||
* either WebSocket fails 3 times to get a return heartbeat both are forced to be recreated.
|
* either WebSocket fails to get a return heartbeat after {@link SignalWebSocketHealthMonitor#KEEP_ALIVE_TIMEOUT} seconds, both are forced to be recreated.
|
||||||
*/
|
*/
|
||||||
private class KeepAliveSender extends Thread {
|
private class KeepAliveSender extends Thread {
|
||||||
|
|
||||||
|
@ -148,20 +157,26 @@ public final class SignalWebSocketHealthMonitor implements HealthMonitor {
|
||||||
identified.lastKeepAliveReceived = System.currentTimeMillis();
|
identified.lastKeepAliveReceived = System.currentTimeMillis();
|
||||||
unidentified.lastKeepAliveReceived = System.currentTimeMillis();
|
unidentified.lastKeepAliveReceived = System.currentTimeMillis();
|
||||||
|
|
||||||
|
long keepAliveSendTime = System.currentTimeMillis();
|
||||||
while (shouldKeepRunning && isKeepAliveNecessary()) {
|
while (shouldKeepRunning && isKeepAliveNecessary()) {
|
||||||
try {
|
try {
|
||||||
sleepTimer.sleep(KEEP_ALIVE_SEND_CADENCE);
|
long nextKeepAliveSendTime = (keepAliveSendTime + KEEP_ALIVE_SEND_CADENCE);
|
||||||
|
sleepUntil(nextKeepAliveSendTime);
|
||||||
|
|
||||||
if (shouldKeepRunning && isKeepAliveNecessary()) {
|
if (shouldKeepRunning && isKeepAliveNecessary()) {
|
||||||
long keepAliveRequiredSinceTime = System.currentTimeMillis() - MAX_TIME_SINCE_SUCCESSFUL_KEEP_ALIVE;
|
keepAliveSendTime = System.currentTimeMillis();
|
||||||
|
signalWebSocket.sendKeepAlive();
|
||||||
|
}
|
||||||
|
|
||||||
if (identified.lastKeepAliveReceived < keepAliveRequiredSinceTime || unidentified.lastKeepAliveReceived < keepAliveRequiredSinceTime) {
|
final long responseRequiredTime = keepAliveSendTime + KEEP_ALIVE_TIMEOUT;
|
||||||
|
sleepUntil(responseRequiredTime);
|
||||||
|
|
||||||
|
if (shouldKeepRunning && isKeepAliveNecessary()) {
|
||||||
|
if (identified.lastKeepAliveReceived < keepAliveSendTime || unidentified.lastKeepAliveReceived < keepAliveSendTime) {
|
||||||
Log.w(TAG, "Missed keep alives, identified last: " + identified.lastKeepAliveReceived +
|
Log.w(TAG, "Missed keep alives, identified last: " + identified.lastKeepAliveReceived +
|
||||||
" unidentified last: " + unidentified.lastKeepAliveReceived +
|
" unidentified last: " + unidentified.lastKeepAliveReceived +
|
||||||
" needed by: " + keepAliveRequiredSinceTime);
|
" needed by: " + responseRequiredTime);
|
||||||
signalWebSocket.forceNewWebSockets();
|
signalWebSocket.forceNewWebSockets();
|
||||||
} else {
|
|
||||||
signalWebSocket.sendKeepAlive();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
@ -170,6 +185,19 @@ public final class SignalWebSocketHealthMonitor implements HealthMonitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sleepUntil(long timeMs) {
|
||||||
|
while (System.currentTimeMillis() < timeMs) {
|
||||||
|
long waitTime = timeMs - System.currentTimeMillis();
|
||||||
|
if (waitTime > 0) {
|
||||||
|
try {
|
||||||
|
sleepTimer.sleep(waitTime);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
shouldKeepRunning = false;
|
shouldKeepRunning = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,8 @@ import static org.whispersystems.signalservice.internal.websocket.WebSocketProto
|
||||||
|
|
||||||
public class WebSocketConnection extends WebSocketListener {
|
public class WebSocketConnection extends WebSocketListener {
|
||||||
|
|
||||||
private static final String TAG = WebSocketConnection.class.getSimpleName();
|
private static final String TAG = WebSocketConnection.class.getSimpleName();
|
||||||
public static final int KEEPALIVE_TIMEOUT_SECONDS = 30;
|
public static final int KEEPALIVE_FREQUENCY_SECONDS = 30;
|
||||||
|
|
||||||
private final LinkedList<WebSocketRequestMessage> incomingRequests = new LinkedList<>();
|
private final LinkedList<WebSocketRequestMessage> incomingRequests = new LinkedList<>();
|
||||||
private final Map<Long, OutgoingRequest> outgoingRequests = new HashMap<>();
|
private final Map<Long, OutgoingRequest> outgoingRequests = new HashMap<>();
|
||||||
|
@ -143,9 +143,9 @@ public class WebSocketConnection extends WebSocketListener {
|
||||||
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().sslSocketFactory(new Tls12SocketFactory(socketFactory.first()),
|
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().sslSocketFactory(new Tls12SocketFactory(socketFactory.first()),
|
||||||
socketFactory.second())
|
socketFactory.second())
|
||||||
.connectionSpecs(serviceUrl.getConnectionSpecs().orElse(Util.immutableList(ConnectionSpec.RESTRICTED_TLS)))
|
.connectionSpecs(serviceUrl.getConnectionSpecs().orElse(Util.immutableList(ConnectionSpec.RESTRICTED_TLS)))
|
||||||
.readTimeout(KEEPALIVE_TIMEOUT_SECONDS + 10, TimeUnit.SECONDS)
|
.readTimeout(KEEPALIVE_FREQUENCY_SECONDS + 10, TimeUnit.SECONDS)
|
||||||
.dns(dns.orElse(Dns.SYSTEM))
|
.dns(dns.orElse(Dns.SYSTEM))
|
||||||
.connectTimeout(KEEPALIVE_TIMEOUT_SECONDS + 10, TimeUnit.SECONDS);
|
.connectTimeout(KEEPALIVE_FREQUENCY_SECONDS + 10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
for (Interceptor interceptor : interceptors) {
|
for (Interceptor interceptor : interceptors) {
|
||||||
clientBuilder.addInterceptor(interceptor);
|
clientBuilder.addInterceptor(interceptor);
|
||||||
|
|
Loading…
Add table
Reference in a new issue