From f67dbb60d3bb3b2047e037dfcb9cd8ce1c390119 Mon Sep 17 00:00:00 2001 From: Jeremy Kahn Date: Fri, 14 Jul 2023 17:21:25 -0500 Subject: [PATCH] feat(connection-test): display failed tracker connections (#129) --- .../Shell/ConnectionTestResults.tsx | 20 +++++++++-- src/components/Shell/PeerList.tsx | 4 ++- src/components/Shell/useConnectionTest.ts | 21 +++++++++--- src/contexts/ShellContext.ts | 7 +++- src/services/ConnectionTest/ConnectionTest.ts | 33 ++++++++++++++++--- 5 files changed, 71 insertions(+), 14 deletions(-) diff --git a/src/components/Shell/ConnectionTestResults.tsx b/src/components/Shell/ConnectionTestResults.tsx index e1fd3ee..7f4c83c 100644 --- a/src/components/Shell/ConnectionTestResults.tsx +++ b/src/components/Shell/ConnectionTestResults.tsx @@ -3,6 +3,9 @@ import Tooltip from '@mui/material/Tooltip' import Typography from '@mui/material/Typography' import Circle from '@mui/icons-material/FiberManualRecord' import { Box } from '@mui/system' +import ReportIcon from '@mui/icons-material/Report' + +import { TrackerConnection } from 'services/ConnectionTest/ConnectionTest' import { ConnectionTestResults as IConnectionTestResults } from './useConnectionTest' @@ -10,9 +13,22 @@ interface ConnectionTestResultsProps { connectionTestResults: IConnectionTestResults } export const ConnectionTestResults = ({ - connectionTestResults: { hasHost, hasRelay, hasTracker }, + connectionTestResults: { hasHost, hasRelay, trackerConnection }, }: ConnectionTestResultsProps) => { - if (!hasTracker) { + if (trackerConnection === TrackerConnection.FAILED) { + return ( + + + + Server connection failed + + + ) + } + + if (trackerConnection !== TrackerConnection.CONNECTED) { return ( { const [hasHost, setHasHost] = useState(false) const [hasRelay, setHasRelay] = useState(false) - const [hasTracker, setHasTracker] = useState(false) + const [trackerConnection, setTrackerConnection] = useState( + TrackerConnection.SEARCHING + ) useEffect(() => { const checkRtcConnection = async () => { @@ -83,14 +86,22 @@ export const useConnectionTest = () => { })() ;(async () => { while (true) { - const connectionTest = new ConnectionTest() - setHasTracker(connectionTest.testTrackerConnection()) + try { + const connectionTest = new ConnectionTest() + const trackerConnectionTestResult = + connectionTest.testTrackerConnection() + + setTrackerConnection(trackerConnectionTestResult) + } catch (e) { + setTrackerConnection(TrackerConnection.FAILED) + } + await sleep(trackerPollInterval) } })() }, []) return { - connectionTestResults: { hasHost, hasRelay, hasTracker }, + connectionTestResults: { hasHost, hasRelay, trackerConnection }, } } diff --git a/src/contexts/ShellContext.ts b/src/contexts/ShellContext.ts index da920c0..16704e6 100644 --- a/src/contexts/ShellContext.ts +++ b/src/contexts/ShellContext.ts @@ -4,6 +4,7 @@ import { AlertOptions } from 'models/shell' import { AudioState, ScreenShareState, VideoState, Peer } from 'models/chat' import { PeerConnectionType } from 'services/PeerRoom/PeerRoom' import { ConnectionTestResults } from 'components/Shell/useConnectionTest' +import { TrackerConnection } from 'services/ConnectionTest/ConnectionTest' interface ShellContextProps { tabHasFocus: boolean @@ -62,5 +63,9 @@ export const ShellContext = createContext({ setPeerAudios: () => {}, customUsername: '', setCustomUsername: () => {}, - connectionTestResults: { hasHost: false, hasRelay: false, hasTracker: false }, + connectionTestResults: { + hasHost: false, + hasRelay: false, + trackerConnection: TrackerConnection.SEARCHING, + }, }) diff --git a/src/services/ConnectionTest/ConnectionTest.ts b/src/services/ConnectionTest/ConnectionTest.ts index f076287..1523f04 100644 --- a/src/services/ConnectionTest/ConnectionTest.ts +++ b/src/services/ConnectionTest/ConnectionTest.ts @@ -8,12 +8,18 @@ export enum ConnectionTestEvents { HAS_RELAY_CHANGED = 'HAS_RELAY_CHANGED', } +export enum TrackerConnection { + SEARCHING = 'SEARCHING', + CONNECTED = 'CONNECTED', + FAILED = 'FAILED', +} + export type ConnectionTestEvent = CustomEvent const checkExperationTime = 10 * 1000 export class ConnectionTest extends EventTarget { - hasTracker = false + trackerConnection = TrackerConnection.SEARCHING hasHost = false hasRelay = false hasPeerReflexive = false @@ -100,17 +106,34 @@ export class ConnectionTest extends EventTarget { testTrackerConnection() { const trackers = getTrackers() - const readyStates = Object.values(trackers).map( - ({ readyState }) => readyState + const trackerSockets = Object.values(trackers) + + if (trackerSockets.length === 0) { + // Trystero has not yet initialized tracker sockets + this.trackerConnection = TrackerConnection.SEARCHING + return this.trackerConnection + } + + const readyStates = trackerSockets.map(({ readyState }) => readyState) + + const haveAllTrackerConnectionsFailed = readyStates.every( + readyState => readyState === WebSocket.CLOSED ) + if (haveAllTrackerConnectionsFailed) { + this.trackerConnection = TrackerConnection.FAILED + throw new Error('Could not connect to a WebTorrent tracker') + } + const areAnyTrackersConnected = readyStates.some( readyState => readyState === WebSocket.OPEN ) - this.hasTracker = areAnyTrackersConnected + this.trackerConnection = areAnyTrackersConnected + ? TrackerConnection.CONNECTED + : TrackerConnection.SEARCHING - return this.hasTracker + return this.trackerConnection } }