add ice restarts to reconnection logic.

This commit is contained in:
Miroslav Šedivý 2021-06-27 22:07:42 +02:00
parent 3edb97e784
commit 14bda1a028
4 changed files with 35 additions and 7 deletions

View File

@ -86,18 +86,23 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
// try to downgrade quality if it happend many times // try to downgrade quality if it happend many times
if (++webrtcCongestion >= WEBRTC_RECONN_FAILED_ATTEMPTS) { if (++webrtcCongestion >= WEBRTC_RECONN_FAILED_ATTEMPTS) {
webrtcCongestion = 0
const quality = this._webrtcQualityDowngrade(this._state.webrtc.video) const quality = this._webrtcQualityDowngrade(this._state.webrtc.video)
// downgrade if lower video quality exists // downgrade if lower video quality exists
if (quality && this.webrtc.connected) { if (quality && this.webrtc.connected) {
this.setVideo(quality) this.setVideo(quality)
webrtcCongestion = 0 }
// try to perform ice restart, if available
if (this.webrtc.open) {
this.websocket.send(EVENT.SIGNAL_RESTART)
return return
} }
// try to reconnect // try to reconnect
this._webrtcReconnect() this._webrtcReconnect()
webrtcCongestion = 0
} }
}) })
} }

View File

@ -125,6 +125,18 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
Vue.set(this._state.connection.webrtc, 'video', video) Vue.set(this._state.connection.webrtc, 'video', video)
} }
protected async [EVENT.SIGNAL_RESTART]({ event, sdp }: message.SignalAnswer) {
this._log.debug('EVENT.SIGNAL_RESTART')
this.emit('connection.webrtc.sdp', 'remote', sdp)
const localSdp = await this._connection.webrtc.offer(sdp)
this._connection.websocket.send(EVENT.SIGNAL_ANSWER, {
sdp: localSdp,
})
this.emit('connection.webrtc.sdp', 'local', localSdp)
}
protected [EVENT.SIGNAL_CANDIDATE]({ event, ...candidate }: message.SignalCandidate) { protected [EVENT.SIGNAL_CANDIDATE]({ event, ...candidate }: message.SignalCandidate) {
this._log.debug('EVENT.SIGNAL_CANDIDATE') this._log.debug('EVENT.SIGNAL_CANDIDATE')
this._connection.webrtc.setCandidate(candidate) this._connection.webrtc.setCandidate(candidate)

View File

@ -54,15 +54,16 @@ export class NekoWebRTC extends EventEmitter<NekoWebRTCEvents> {
return typeof RTCPeerConnection !== 'undefined' && typeof RTCPeerConnection.prototype.addTransceiver !== 'undefined' return typeof RTCPeerConnection !== 'undefined' && typeof RTCPeerConnection.prototype.addTransceiver !== 'undefined'
} }
get connected() { get open() {
return ( return (
typeof this._peer !== 'undefined' && typeof this._peer !== 'undefined' && typeof this._channel !== 'undefined' && this._channel.readyState == 'open'
['connected', 'checking', 'completed'].includes(this._state) &&
typeof this._channel !== 'undefined' &&
this._channel.readyState == 'open'
) )
} }
get connected() {
return this.open && ['connected', 'checking', 'completed'].includes(this._state)
}
public async setCandidate(candidate: RTCIceCandidateInit) { public async setCandidate(candidate: RTCIceCandidateInit) {
if (!this._peer) { if (!this._peer) {
this._candidates.push(candidate) this._candidates.push(candidate)
@ -137,6 +138,15 @@ export class NekoWebRTC extends EventEmitter<NekoWebRTCEvents> {
this._peer.ondatachannel = this.onDataChannel.bind(this) this._peer.ondatachannel = this.onDataChannel.bind(this)
this._peer.addTransceiver('audio', { direction: 'recvonly' }) this._peer.addTransceiver('audio', { direction: 'recvonly' })
this._peer.addTransceiver('video', { direction: 'recvonly' }) this._peer.addTransceiver('video', { direction: 'recvonly' })
return await this.offer(sdp)
}
public async offer(sdp: string) {
if (!this._peer) {
throw new Error('attempting to set offer for nonexistent peer')
}
this._peer.setRemoteDescription({ type: 'offer', sdp }) this._peer.setRemoteDescription({ type: 'offer', sdp })
if (this._candidates.length > 0) { if (this._candidates.length > 0) {

View File

@ -3,6 +3,7 @@ export const SYSTEM_ADMIN = 'system/admin'
export const SYSTEM_DISCONNECT = 'system/disconnect' export const SYSTEM_DISCONNECT = 'system/disconnect'
export const SIGNAL_REQUEST = 'signal/request' export const SIGNAL_REQUEST = 'signal/request'
export const SIGNAL_RESTART = 'signal/restart'
export const SIGNAL_ANSWER = 'signal/answer' export const SIGNAL_ANSWER = 'signal/answer'
export const SIGNAL_PROVIDE = 'signal/provide' export const SIGNAL_PROVIDE = 'signal/provide'
export const SIGNAL_CANDIDATE = 'signal/candidate' export const SIGNAL_CANDIDATE = 'signal/candidate'