connection make websocket async.

This commit is contained in:
Miroslav Šedivý 2021-06-20 23:56:34 +02:00
parent b9b311c6de
commit d77a795438

View File

@ -7,16 +7,19 @@ import { NekoWebSocket } from './websocket'
import { NekoWebRTC, WebRTCStats } from './webrtc' import { NekoWebRTC, WebRTCStats } from './webrtc'
import { Connection } from '../types/state' import { Connection } from '../types/state'
const websocketTimer = 1000
const webrtcTimer = 10000
export interface NekoConnectionEvents { export interface NekoConnectionEvents {
disconnect: (error?: Error) => void disconnect: (error?: Error) => void
} }
export class NekoConnection extends EventEmitter<NekoConnectionEvents> { export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
private _shouldReconnect = false
private _url: string private _url: string
private _token: string private _token: string
private _state: Connection private _state: Connection
private _log: Logger private _log: Logger
private _shouldReconnect = false
public websocket = new NekoWebSocket() public websocket = new NekoWebSocket()
public webrtc = new NekoWebRTC() public webrtc = new NekoWebRTC()
@ -113,15 +116,20 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
} }
public async connect(video?: string): Promise<void> { public async connect(video?: string): Promise<void> {
try {
await this._websocketConnect() await this._websocketConnect()
if (video && !this._state.webrtc.videos.includes(video)) { if (video && !this._state.webrtc.videos.includes(video)) {
throw new Error('video id not found') throw new Error('video id not found')
} }
this._webrtcConnect(video) await this._webrtcConnect(video)
this._shouldReconnect = true this._shouldReconnect = true
} catch (e) {
this.disconnect()
throw e
}
} }
public disconnect() { public disconnect() {
@ -135,12 +143,29 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
} }
async _websocketConnect() { async _websocketConnect() {
Vue.set(this._state, 'status', 'connecting')
let url = this._url let url = this._url
if (this._token) { if (this._token) {
url += '?token=' + encodeURIComponent(this._token) url += '?token=' + encodeURIComponent(this._token)
} }
await this.websocket.connect(url) this.websocket.connect(url)
await new Promise<void>((res, rej) => {
const timeout = window.setTimeout(() => {
this.websocket.disconnect()
rej(new Error('timeouted'))
}, websocketTimer)
this.websocket.once('connected', () => {
window.clearTimeout(timeout)
res()
})
this.websocket.once('disconnected', (reason) => {
window.clearTimeout(timeout)
rej(reason)
})
})
} }
_websocketIsReconnecting = false _websocketIsReconnecting = false
@ -168,17 +193,33 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
}, 0) }, 0)
} }
_webrtcConnect(video?: string) { async _webrtcConnect(video?: string) {
if (video && !this._state.webrtc.videos.includes(video)) { if (video && !this._state.webrtc.videos.includes(video)) {
throw new Error('video id not found') throw new Error('video id not found')
} }
Vue.set(this._state, 'status', 'connecting')
this.websocket.send(EVENT.SIGNAL_REQUEST, { video: video }) this.websocket.send(EVENT.SIGNAL_REQUEST, { video: video })
await new Promise<void>((res, rej) => {
const timeout = window.setTimeout(() => {
this.webrtc.disconnect()
rej(new Error('timeouted'))
}, webrtcTimer)
this.webrtc.once('connected', () => {
window.clearTimeout(timeout)
res()
})
this.webrtc.once('disconnected', (reason) => {
window.clearTimeout(timeout)
rej(reason)
})
})
} }
_webrtcReconnTimer?: number _webrtcIsReconnecting = false
_webrtcReconnect() { _webrtcReconnect() {
if (this._webrtcReconnTimer) { if (this._webrtcIsReconnecting) {
this._log.debug(`webrtc reconnection already in progress`) this._log.debug(`webrtc reconnection already in progress`)
return return
} }
@ -186,22 +227,18 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
const lastVideo = this._state.webrtc.video ?? undefined const lastVideo = this._state.webrtc.video ?? undefined
this._log.debug(`starting webrtc reconnection`) this._log.debug(`starting webrtc reconnection`)
const reconnFunc = async () => { setTimeout(async () => {
if (!this._shouldReconnect || !this.websocket.connected || this.webrtc.connected) { while (this._shouldReconnect && this.websocket.connected) {
clearInterval(this._webrtcReconnTimer)
this._webrtcReconnTimer = undefined
this._log.debug(`webrtc reconnection finished`)
return
}
try { try {
this._webrtcConnect(lastVideo) await this._webrtcConnect(lastVideo)
break
} catch (e) { } catch (e) {
this._log.debug(`webrtc reconnection failed`, e) this._log.debug(`webrtc reconnection failed`, e)
} }
} }
this._webrtcReconnTimer = window.setInterval(reconnFunc, 1000) this._webrtcIsReconnecting = false
reconnFunc() this._log.debug(`webrtc reconnection finished`)
}, 0)
} }
} }