From b56069c96e1e6f4df5470bb980506548ee2e1958 Mon Sep 17 00:00:00 2001 From: sergystepanov Date: Sat, 20 Feb 2021 18:45:43 +0300 Subject: [PATCH] Fix stream freeze (#279) * Fix D-pad key and overlay * Add Video element error reporting * Terminate clientside ws ping on the connection terminate --- web/js/controller.js | 5 ++++- web/js/network/socket.js | 26 ++++++++++++++++++++++---- web/js/stream/stream.js | 21 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/web/js/controller.js b/web/js/controller.js index d53c6f39..b963924b 100644 --- a/web/js/controller.js +++ b/web/js/controller.js @@ -423,7 +423,10 @@ event.sub(MEDIA_STREAM_CANDIDATE_FLUSH, () => rtcp.flushCandidate()); event.sub(MEDIA_STREAM_READY, () => rtcp.start()); event.sub(CONNECTION_READY, onConnectionReady); - event.sub(CONNECTION_CLOSED, () => input.poll().disable()); + event.sub(CONNECTION_CLOSED, () => { + input.poll().disable(); + socket.abort(); + }); event.sub(LATENCY_CHECK_REQUESTED, onLatencyCheck); event.sub(GAMEPAD_CONNECTED, () => popup('Gamepad connected')); event.sub(GAMEPAD_DISCONNECTED, () => popup('Gamepad disconnected')); diff --git a/web/js/network/socket.js b/web/js/network/socket.js index 480850a1..0781bf93 100644 --- a/web/js/network/socket.js +++ b/web/js/network/socket.js @@ -23,8 +23,8 @@ const socket = (() => { Below is high level implementation of ping. // TODO: find the best ping time, currently 2 seconds works well in Chrome+Firefox */ - const pingIntervalMs = 2000; // 2 secs - // const pingIntervalMs = 1000 / 5; // too much + const pingIntervalMs = 2000; + let pingIntervalId = 0; let conn; let curPacketId = ''; @@ -37,10 +37,12 @@ const socket = (() => { // Clear old roomID conn.onopen = () => { + if (pingIntervalId > 0) return; + log.info('[ws] <- open connection'); log.info(`[ws] -> setting ping interval to ${pingIntervalMs}ms`); // !to add destructor if SPA - setInterval(ping, pingIntervalMs) + pingIntervalId = setInterval(ping, pingIntervalMs) }; conn.onerror = error => log.error(`[ws] ${error}`); conn.onclose = () => log.info('[ws] closed'); @@ -89,13 +91,28 @@ const socket = (() => { }; }; + /** + * Abnormal connection termination cleanup. + */ + const abort = () => { + if (pingIntervalId < 0) return; + + log.info('[ws] ping has been disabled'); + clearInterval(pingIntervalId); + pingIntervalId = 0; + } + // TODO: format the package with time const ping = () => { const time = Date.now(); send({"id": "heartbeat", "data": time.toString()}); event.pub(PING_REQUEST, {time: time}); } - const send = (data) => conn.send(JSON.stringify(data)); + const send = (data) => { + if (conn.readyState === 1) { + conn.send(JSON.stringify(data)); + } + } const latency = (workers, packetId) => send({ "id": "checkLatency", "data": JSON.stringify(workers), @@ -118,6 +135,7 @@ const socket = (() => { return { init: init, + abort: abort, send: send, latency: latency, saveGame: saveGame, diff --git a/web/js/stream/stream.js b/web/js/stream/stream.js index 858689d7..8ee5f6f7 100644 --- a/web/js/stream/stream.js +++ b/web/js/stream/stream.js @@ -46,6 +46,27 @@ const stream = (() => { const getVideoEl = () => screen + screen.onerror = (e) => { + // video playback failed - show a message saying why + switch (e.target.error.code) { + case e.target.error.MEDIA_ERR_ABORTED: + log.error('You aborted the video playback.'); + break; + case e.target.error.MEDIA_ERR_NETWORK: + log.error('A network error caused the video download to fail part-way.'); + break; + case e.target.error.MEDIA_ERR_DECODE: + log.error('The video playback was aborted due to a corruption problem or because the video used features your browser did not support.'); + break; + case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED: + log.error('The video could not be loaded, either because the server or network failed or because the format is not supported.'); + break; + default: + log.error('An unknown video error occurred.'); + break; + } + }; + screen.addEventListener('loadedmetadata', () => { if (state.screen !== screen) { state.screen.setAttribute('width', screen.videoWidth);