feat(connection-test): display failed tracker connections (#129)
This commit is contained in:
		
							parent
							
								
									291ed0c2b9
								
							
						
					
					
						commit
						f67dbb60d3
					
				| @ -3,6 +3,9 @@ import Tooltip from '@mui/material/Tooltip' | |||||||
| import Typography from '@mui/material/Typography' | import Typography from '@mui/material/Typography' | ||||||
| import Circle from '@mui/icons-material/FiberManualRecord' | import Circle from '@mui/icons-material/FiberManualRecord' | ||||||
| import { Box } from '@mui/system' | import { Box } from '@mui/system' | ||||||
|  | import ReportIcon from '@mui/icons-material/Report' | ||||||
|  | 
 | ||||||
|  | import { TrackerConnection } from 'services/ConnectionTest/ConnectionTest' | ||||||
| 
 | 
 | ||||||
| import { ConnectionTestResults as IConnectionTestResults } from './useConnectionTest' | import { ConnectionTestResults as IConnectionTestResults } from './useConnectionTest' | ||||||
| 
 | 
 | ||||||
| @ -10,9 +13,22 @@ interface ConnectionTestResultsProps { | |||||||
|   connectionTestResults: IConnectionTestResults |   connectionTestResults: IConnectionTestResults | ||||||
| } | } | ||||||
| export const ConnectionTestResults = ({ | export const ConnectionTestResults = ({ | ||||||
|   connectionTestResults: { hasHost, hasRelay, hasTracker }, |   connectionTestResults: { hasHost, hasRelay, trackerConnection }, | ||||||
| }: ConnectionTestResultsProps) => { | }: ConnectionTestResultsProps) => { | ||||||
|   if (!hasTracker) { |   if (trackerConnection === TrackerConnection.FAILED) { | ||||||
|  |     return ( | ||||||
|  |       <Typography variant="subtitle2"> | ||||||
|  |         <Box | ||||||
|  |           sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }} | ||||||
|  |         > | ||||||
|  |           <ReportIcon color="error" sx={{ mr: 1 }} /> | ||||||
|  |           <span>Server connection failed</span> | ||||||
|  |         </Box> | ||||||
|  |       </Typography> | ||||||
|  |     ) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (trackerConnection !== TrackerConnection.CONNECTED) { | ||||||
|     return ( |     return ( | ||||||
|       <Typography variant="subtitle2"> |       <Typography variant="subtitle2"> | ||||||
|         <Box |         <Box | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ import { PeerListHeader } from 'components/Shell/PeerListHeader' | |||||||
| import { Username } from 'components/Username/Username' | import { Username } from 'components/Username/Username' | ||||||
| import { AudioState, Peer } from 'models/chat' | import { AudioState, Peer } from 'models/chat' | ||||||
| import { PeerConnectionType } from 'services/PeerRoom/PeerRoom' | import { PeerConnectionType } from 'services/PeerRoom/PeerRoom' | ||||||
|  | import { TrackerConnection } from 'services/ConnectionTest/ConnectionTest' | ||||||
| import { routes } from 'config/routes' | import { routes } from 'config/routes' | ||||||
| 
 | 
 | ||||||
| import { PeerListItem } from './PeerListItem' | import { PeerListItem } from './PeerListItem' | ||||||
| @ -113,7 +114,8 @@ export const PeerList = ({ | |||||||
|         ))} |         ))} | ||||||
|         {peerList.length === 0 && |         {peerList.length === 0 && | ||||||
|         typeof roomId === 'string' && |         typeof roomId === 'string' && | ||||||
|         connectionTestResults.hasTracker && |         connectionTestResults.trackerConnection === | ||||||
|  |           TrackerConnection.CONNECTED && | ||||||
|         connectionTestResults.hasHost ? ( |         connectionTestResults.hasHost ? ( | ||||||
|           <> |           <> | ||||||
|             <Box |             <Box | ||||||
|  | |||||||
| @ -4,12 +4,13 @@ import { | |||||||
|   ConnectionTest, |   ConnectionTest, | ||||||
|   ConnectionTestEvent, |   ConnectionTestEvent, | ||||||
|   ConnectionTestEvents, |   ConnectionTestEvents, | ||||||
|  |   TrackerConnection, | ||||||
| } from 'services/ConnectionTest/ConnectionTest' | } from 'services/ConnectionTest/ConnectionTest' | ||||||
| 
 | 
 | ||||||
| export interface ConnectionTestResults { | export interface ConnectionTestResults { | ||||||
|   hasHost: boolean |   hasHost: boolean | ||||||
|   hasRelay: boolean |   hasRelay: boolean | ||||||
|   hasTracker: boolean |   trackerConnection: TrackerConnection | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const rtcPollInterval = 20 * 1000 | const rtcPollInterval = 20 * 1000 | ||||||
| @ -18,7 +19,9 @@ const trackerPollInterval = 5 * 1000 | |||||||
| export const useConnectionTest = () => { | export const useConnectionTest = () => { | ||||||
|   const [hasHost, setHasHost] = useState(false) |   const [hasHost, setHasHost] = useState(false) | ||||||
|   const [hasRelay, setHasRelay] = useState(false) |   const [hasRelay, setHasRelay] = useState(false) | ||||||
|   const [hasTracker, setHasTracker] = useState(false) |   const [trackerConnection, setTrackerConnection] = useState( | ||||||
|  |     TrackerConnection.SEARCHING | ||||||
|  |   ) | ||||||
| 
 | 
 | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     const checkRtcConnection = async () => { |     const checkRtcConnection = async () => { | ||||||
| @ -83,14 +86,22 @@ export const useConnectionTest = () => { | |||||||
|     })() |     })() | ||||||
|     ;(async () => { |     ;(async () => { | ||||||
|       while (true) { |       while (true) { | ||||||
|  |         try { | ||||||
|           const connectionTest = new ConnectionTest() |           const connectionTest = new ConnectionTest() | ||||||
|         setHasTracker(connectionTest.testTrackerConnection()) |           const trackerConnectionTestResult = | ||||||
|  |             connectionTest.testTrackerConnection() | ||||||
|  | 
 | ||||||
|  |           setTrackerConnection(trackerConnectionTestResult) | ||||||
|  |         } catch (e) { | ||||||
|  |           setTrackerConnection(TrackerConnection.FAILED) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         await sleep(trackerPollInterval) |         await sleep(trackerPollInterval) | ||||||
|       } |       } | ||||||
|     })() |     })() | ||||||
|   }, []) |   }, []) | ||||||
| 
 | 
 | ||||||
|   return { |   return { | ||||||
|     connectionTestResults: { hasHost, hasRelay, hasTracker }, |     connectionTestResults: { hasHost, hasRelay, trackerConnection }, | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ import { AlertOptions } from 'models/shell' | |||||||
| import { AudioState, ScreenShareState, VideoState, Peer } from 'models/chat' | import { AudioState, ScreenShareState, VideoState, Peer } from 'models/chat' | ||||||
| import { PeerConnectionType } from 'services/PeerRoom/PeerRoom' | import { PeerConnectionType } from 'services/PeerRoom/PeerRoom' | ||||||
| import { ConnectionTestResults } from 'components/Shell/useConnectionTest' | import { ConnectionTestResults } from 'components/Shell/useConnectionTest' | ||||||
|  | import { TrackerConnection } from 'services/ConnectionTest/ConnectionTest' | ||||||
| 
 | 
 | ||||||
| interface ShellContextProps { | interface ShellContextProps { | ||||||
|   tabHasFocus: boolean |   tabHasFocus: boolean | ||||||
| @ -62,5 +63,9 @@ export const ShellContext = createContext<ShellContextProps>({ | |||||||
|   setPeerAudios: () => {}, |   setPeerAudios: () => {}, | ||||||
|   customUsername: '', |   customUsername: '', | ||||||
|   setCustomUsername: () => {}, |   setCustomUsername: () => {}, | ||||||
|   connectionTestResults: { hasHost: false, hasRelay: false, hasTracker: false }, |   connectionTestResults: { | ||||||
|  |     hasHost: false, | ||||||
|  |     hasRelay: false, | ||||||
|  |     trackerConnection: TrackerConnection.SEARCHING, | ||||||
|  |   }, | ||||||
| }) | }) | ||||||
|  | |||||||
| @ -8,12 +8,18 @@ export enum ConnectionTestEvents { | |||||||
|   HAS_RELAY_CHANGED = 'HAS_RELAY_CHANGED', |   HAS_RELAY_CHANGED = 'HAS_RELAY_CHANGED', | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export enum TrackerConnection { | ||||||
|  |   SEARCHING = 'SEARCHING', | ||||||
|  |   CONNECTED = 'CONNECTED', | ||||||
|  |   FAILED = 'FAILED', | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export type ConnectionTestEvent = CustomEvent<ConnectionTest> | export type ConnectionTestEvent = CustomEvent<ConnectionTest> | ||||||
| 
 | 
 | ||||||
| const checkExperationTime = 10 * 1000 | const checkExperationTime = 10 * 1000 | ||||||
| 
 | 
 | ||||||
| export class ConnectionTest extends EventTarget { | export class ConnectionTest extends EventTarget { | ||||||
|   hasTracker = false |   trackerConnection = TrackerConnection.SEARCHING | ||||||
|   hasHost = false |   hasHost = false | ||||||
|   hasRelay = false |   hasRelay = false | ||||||
|   hasPeerReflexive = false |   hasPeerReflexive = false | ||||||
| @ -100,17 +106,34 @@ export class ConnectionTest extends EventTarget { | |||||||
|   testTrackerConnection() { |   testTrackerConnection() { | ||||||
|     const trackers = getTrackers() |     const trackers = getTrackers() | ||||||
| 
 | 
 | ||||||
|     const readyStates = Object.values(trackers).map( |     const trackerSockets = Object.values(trackers) | ||||||
|       ({ readyState }) => readyState | 
 | ||||||
|  |     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( |     const areAnyTrackersConnected = readyStates.some( | ||||||
|       readyState => readyState === WebSocket.OPEN |       readyState => readyState === WebSocket.OPEN | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     this.hasTracker = areAnyTrackersConnected |     this.trackerConnection = areAnyTrackersConnected | ||||||
|  |       ? TrackerConnection.CONNECTED | ||||||
|  |       : TrackerConnection.SEARCHING | ||||||
| 
 | 
 | ||||||
|     return this.hasTracker |     return this.trackerConnection | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user