forked from Shiloh/remnantchat
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…
Reference in New Issue
Block a user