mirror of https://github.com/jetkvm/kvm.git
Added exponential backoff to reconnection
Also made the number of reconnect attempts settable Doesn't attempt a reconnection if we intentionally disconnect Make sure the fire-and-forget for TURN activity doesn't result in unhandled promise rejection.
This commit is contained in:
parent
0984ca7e40
commit
69f429d0a5
|
@ -146,6 +146,7 @@ export default function KvmIdRoute() {
|
||||||
const { otaState, setOtaState, setModalView } = useUpdateStore();
|
const { otaState, setOtaState, setModalView } = useUpdateStore();
|
||||||
|
|
||||||
const [loadingMessage, setLoadingMessage] = useState("Connecting to device...");
|
const [loadingMessage, setLoadingMessage] = useState("Connecting to device...");
|
||||||
|
|
||||||
const cleanupAndStopReconnecting = useCallback(
|
const cleanupAndStopReconnecting = useCallback(
|
||||||
function cleanupAndStopReconnecting() {
|
function cleanupAndStopReconnecting() {
|
||||||
console.log("Closing peer connection");
|
console.log("Closing peer connection");
|
||||||
|
@ -182,11 +183,11 @@ export default function KvmIdRoute() {
|
||||||
pc: RTCPeerConnection,
|
pc: RTCPeerConnection,
|
||||||
remoteDescription: RTCSessionDescriptionInit,
|
remoteDescription: RTCSessionDescriptionInit,
|
||||||
) {
|
) {
|
||||||
setLoadingMessage("Setting remote description");
|
setLoadingMessage("Setting remote description type:" + remoteDescription.type);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await pc.setRemoteDescription(new RTCSessionDescription(remoteDescription));
|
await pc.setRemoteDescription(new RTCSessionDescription(remoteDescription));
|
||||||
console.log("[setRemoteSessionDescription] Remote description set successfully");
|
console.log("[setRemoteSessionDescription] Remote description set successfully to: " + remoteDescription.sdp);
|
||||||
setLoadingMessage("Establishing secure connection...");
|
setLoadingMessage("Establishing secure connection...");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
console.error(
|
||||||
|
@ -231,9 +232,15 @@ export default function KvmIdRoute() {
|
||||||
const ignoreOffer = useRef(false);
|
const ignoreOffer = useRef(false);
|
||||||
const isSettingRemoteAnswerPending = useRef(false);
|
const isSettingRemoteAnswerPending = useRef(false);
|
||||||
const makingOffer = useRef(false);
|
const makingOffer = useRef(false);
|
||||||
|
const reconnectAttemptsRef = useRef(20);
|
||||||
|
|
||||||
const wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
const wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
|
|
||||||
|
const reconnectInterval = (attempt: number) => {
|
||||||
|
// Exponential backoff with a max of 10 seconds between attempts
|
||||||
|
return Math.min(500 * 2 ** attempt, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
const { sendMessage, getWebSocket } = useWebSocket(
|
const { sendMessage, getWebSocket } = useWebSocket(
|
||||||
isOnDevice
|
isOnDevice
|
||||||
? `${wsProtocol}//${window.location.host}/webrtc/signaling/client`
|
? `${wsProtocol}//${window.location.host}/webrtc/signaling/client`
|
||||||
|
@ -241,17 +248,16 @@ export default function KvmIdRoute() {
|
||||||
{
|
{
|
||||||
heartbeat: true,
|
heartbeat: true,
|
||||||
retryOnError: true,
|
retryOnError: true,
|
||||||
reconnectAttempts: 15,
|
reconnectAttempts: reconnectAttemptsRef.current,
|
||||||
reconnectInterval: 1000,
|
reconnectInterval: reconnectInterval,
|
||||||
onReconnectStop: () => {
|
onReconnectStop: (attempt: number) => {
|
||||||
console.debug("Reconnect stopped");
|
console.debug("Reconnect stopped after ", attempt, "attempts");
|
||||||
cleanupAndStopReconnecting();
|
cleanupAndStopReconnecting();
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldReconnect(event) {
|
shouldReconnect(event) {
|
||||||
console.debug("[Websocket] shouldReconnect", event);
|
console.debug("[Websocket] shouldReconnect", event);
|
||||||
// TODO: Why true?
|
return !connectionFailed; // we always want to try to reconnect unless we're explicitly stopped
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onClose(event) {
|
onClose(event) {
|
||||||
|
@ -284,6 +290,7 @@ export default function KvmIdRoute() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const parsedMessage = JSON.parse(message.data);
|
const parsedMessage = JSON.parse(message.data);
|
||||||
|
|
||||||
if (parsedMessage.type === "device-metadata") {
|
if (parsedMessage.type === "device-metadata") {
|
||||||
const { deviceVersion } = parsedMessage.data;
|
const { deviceVersion } = parsedMessage.data;
|
||||||
console.debug("[Websocket] Received device-metadata message");
|
console.debug("[Websocket] Received device-metadata message");
|
||||||
|
@ -300,10 +307,12 @@ export default function KvmIdRoute() {
|
||||||
console.log("[Websocket] Device is using new signaling");
|
console.log("[Websocket] Device is using new signaling");
|
||||||
isLegacySignalingEnabled.current = false;
|
isLegacySignalingEnabled.current = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupPeerConnection();
|
setupPeerConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!peerConnection) return;
|
if (!peerConnection) return;
|
||||||
|
|
||||||
if (parsedMessage.type === "answer") {
|
if (parsedMessage.type === "answer") {
|
||||||
console.debug("[Websocket] Received answer");
|
console.debug("[Websocket] Received answer");
|
||||||
const readyForOffer =
|
const readyForOffer =
|
||||||
|
@ -594,7 +603,9 @@ export default function KvmIdRoute() {
|
||||||
api.POST(`${CLOUD_API}/webrtc/turn_activity`, {
|
api.POST(`${CLOUD_API}/webrtc/turn_activity`, {
|
||||||
bytesReceived: bytesReceivedDelta,
|
bytesReceived: bytesReceivedDelta,
|
||||||
bytesSent: bytesSentDelta,
|
bytesSent: bytesSentDelta,
|
||||||
});
|
}).catch(()=>{
|
||||||
|
// we don't care about errors here, but we don't want unhandled promise rejections
|
||||||
|
});
|
||||||
}, 10000);
|
}, 10000);
|
||||||
|
|
||||||
const { setNetworkState} = useNetworkStateStore();
|
const { setNetworkState} = useNetworkStateStore();
|
||||||
|
|
Loading…
Reference in New Issue