mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-15 07:28:30 +00:00
Improve calling reliability with relay server response cache.
Co-authored-by: Cody Henthorne <cody@signal.org>
This commit is contained in:
committed by
Cody Henthorne
parent
92a28f7103
commit
076b47e695
@@ -1033,17 +1033,26 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
public void retrieveTurnServers(@NonNull RemotePeer remotePeer) {
|
||||
networkExecutor.execute(() -> {
|
||||
try {
|
||||
List<TurnServerInfo> turnServerInfos = NetworkResultUtil.toBasicLegacy(SignalNetwork.calling().getTurnServerInfo());
|
||||
List<PeerConnection.IceServer> iceServers = mapToIceServers(turnServerInfos);
|
||||
process((s, p) -> {
|
||||
RemotePeer activePeer = s.getCallInfoState().getActivePeer();
|
||||
if (activePeer != null && activePeer.getCallId().equals(remotePeer.getCallId())) {
|
||||
return p.handleTurnServerUpdate(s, iceServers, TextSecurePreferences.isTurnOnly(context));
|
||||
}
|
||||
List<PeerConnection.IceServer> cachedServers = TurnServerCache.getCachedServers();
|
||||
if (cachedServers != null) {
|
||||
processTurnServers(remotePeer, cachedServers);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.w(TAG, "Ignoring received turn servers for incorrect call id. requesting_call_id: " + remotePeer.getCallId() + " current_call_id: " + (activePeer != null ? activePeer.getCallId() : "null"));
|
||||
return s;
|
||||
});
|
||||
List<TurnServerInfo> turnServerInfos = NetworkResultUtil.toBasicLegacy(SignalNetwork.calling().getTurnServerInfo());
|
||||
|
||||
// Find *any* provided ttl values as long as they are valid.
|
||||
long minTtl = turnServerInfos.stream()
|
||||
.map(TurnServerInfo::getTtl)
|
||||
.filter(ttl -> ttl != null && ttl > 0)
|
||||
.min(Long::compare)
|
||||
.orElse(0L);
|
||||
|
||||
List<PeerConnection.IceServer> iceServers = mapToIceServers(turnServerInfos);
|
||||
|
||||
TurnServerCache.updateCache(iceServers, minTtl);
|
||||
|
||||
processTurnServers(remotePeer, iceServers);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Unable to retrieve turn servers: ", e);
|
||||
process((s, p) -> p.handleSetupFailure(s, remotePeer.getCallId()));
|
||||
@@ -1051,6 +1060,18 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
});
|
||||
}
|
||||
|
||||
private void processTurnServers(RemotePeer remotePeer, List<PeerConnection.IceServer> servers) {
|
||||
process((s, p) -> {
|
||||
RemotePeer activePeer = s.getCallInfoState().getActivePeer();
|
||||
if (activePeer != null && activePeer.getCallId().equals(remotePeer.getCallId())) {
|
||||
return p.handleTurnServerUpdate(s, servers, TextSecurePreferences.isTurnOnly(context));
|
||||
}
|
||||
|
||||
Log.w(TAG, "Ignoring received turn servers for incorrect call id. requesting_call_id: " + remotePeer.getCallId() + " current_call_id: " + (activePeer != null ? activePeer.getCallId() : "null"));
|
||||
return s;
|
||||
});
|
||||
}
|
||||
|
||||
private static List<PeerConnection.IceServer> mapToIceServers(@NonNull List<TurnServerInfo> turnServerInfos) {
|
||||
List<PeerConnection.IceServer> iceServers = new ArrayList<>();
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.service.webrtc
|
||||
|
||||
import android.os.SystemClock
|
||||
import org.webrtc.PeerConnection
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
* Provide an in-memory cache of TURN servers used for calling as the endpoint
|
||||
* is rate limited and the data should be valid for the duration of a app run.
|
||||
*/
|
||||
object TurnServerCache {
|
||||
private var iceServers: List<PeerConnection.IceServer>? = null
|
||||
private var lastUpdated: Duration = Duration.ZERO
|
||||
private var cacheTtl: Duration = Duration.ZERO
|
||||
|
||||
@JvmStatic
|
||||
fun getCachedServers(): List<PeerConnection.IceServer>? {
|
||||
val now = SystemClock.elapsedRealtime().milliseconds
|
||||
|
||||
return if (iceServers != null && now > lastUpdated && now < (lastUpdated + cacheTtl)) {
|
||||
iceServers
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun updateCache(newServers: List<PeerConnection.IceServer>, ttl: Long) {
|
||||
lastUpdated = SystemClock.elapsedRealtime().milliseconds
|
||||
cacheTtl = ttl.seconds
|
||||
|
||||
iceServers = newServers
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.whispersystems.signalservice.api.messages.calls;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.List;
|
||||
@@ -22,6 +21,9 @@ public class TurnServerInfo {
|
||||
@JsonProperty
|
||||
private List<String> urlsWithIps;
|
||||
|
||||
@JsonProperty
|
||||
private Long ttl;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
@@ -42,4 +44,8 @@ public class TurnServerInfo {
|
||||
public List<String> getUrlsWithIps() {
|
||||
return urlsWithIps;
|
||||
}
|
||||
|
||||
public Long getTtl() {
|
||||
return ttl;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user