livekit-client
Version:
JavaScript/TypeScript client SDK for LiveKit
85 lines (79 loc) • 2.58 kB
text/typescript
import log from '../../logger';
import { RoomEvent } from '../../room/events';
import { Checker } from './Checker';
export class WebRTCCheck extends Checker {
get description(): string {
return 'Establishing WebRTC connection';
}
protected async perform(): Promise<void> {
let hasTcp = false;
let hasIpv4Udp = false;
this.room.on(RoomEvent.SignalConnected, () => {
const prevTrickle = this.room.engine.client.onTrickle;
const candidates: RTCIceCandidate[] = [];
this.room.engine.client.onTrickle = (sd, target) => {
if (sd.candidate) {
const candidate = new RTCIceCandidate(sd);
candidates.push(candidate);
let str = `${candidate.protocol} ${candidate.address}:${candidate.port} ${candidate.type}`;
if (candidate.address) {
if (isIPPrivate(candidate.address)) {
str += ' (private)';
} else {
if (candidate.protocol === 'tcp' && candidate.tcpType === 'passive') {
hasTcp = true;
str += ' (passive)';
} else if (candidate.protocol === 'udp') {
hasIpv4Udp = true;
}
}
}
this.appendMessage(str);
}
if (prevTrickle) {
prevTrickle(sd, target);
}
};
if (this.room.engine.pcManager) {
this.room.engine.pcManager.subscriber.onIceCandidateError = (ev) => {
if (ev instanceof RTCPeerConnectionIceErrorEvent) {
this.appendWarning(
`error with ICE candidate: ${ev.errorCode} ${ev.errorText} ${ev.url}`,
);
}
};
}
});
try {
await this.connect();
log.info('now the room is connected');
} catch (err) {
this.appendWarning('ports need to be open on firewall in order to connect.');
throw err;
}
if (!hasTcp) {
this.appendWarning('Server is not configured for ICE/TCP');
}
if (!hasIpv4Udp) {
this.appendWarning(
'No public IPv4 UDP candidates were found. Your server is likely not configured correctly',
);
}
}
}
function isIPPrivate(address: string): boolean {
const parts = address.split('.');
if (parts.length === 4) {
if (parts[0] === '10') {
return true;
} else if (parts[0] === '192' && parts[1] === '168') {
return true;
} else if (parts[0] === '172') {
const second = parseInt(parts[1], 10);
if (second >= 16 && second <= 31) {
return true;
}
}
}
return false;
}