mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
connection open & close.
This commit is contained in:
parent
b8453b3211
commit
9f13d43da5
@ -14,72 +14,69 @@ const WEBRTC_RECONN_MAX_LOSS = 25
|
|||||||
const WEBRTC_RECONN_FAILED_ATTEMPTS = 5
|
const WEBRTC_RECONN_FAILED_ATTEMPTS = 5
|
||||||
|
|
||||||
export interface NekoConnectionEvents {
|
export interface NekoConnectionEvents {
|
||||||
disconnect: (error?: Error) => void
|
close: (error?: Error) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
||||||
private _state: Connection
|
private _state: Connection
|
||||||
|
|
||||||
public websocket = new NekoWebSocket()
|
public websocket = new NekoWebSocket()
|
||||||
public _websocket_reconn: Reconnector
|
|
||||||
|
|
||||||
public webrtc = new NekoWebRTC()
|
public webrtc = new NekoWebRTC()
|
||||||
public _webrtc_reconn: Reconnector
|
|
||||||
|
private _reconnector: {
|
||||||
|
websocket: Reconnector
|
||||||
|
webrtc: Reconnector
|
||||||
|
}
|
||||||
|
|
||||||
constructor(state: Connection) {
|
constructor(state: Connection) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
this._state = state
|
this._state = state
|
||||||
this._websocket_reconn = new Reconnector(new WebsocketReconnector(state, this.websocket), state.websocket.config)
|
this._reconnector = {
|
||||||
this._webrtc_reconn = new Reconnector(
|
websocket: new Reconnector(new WebsocketReconnector(state, this.websocket), state.websocket.config),
|
||||||
new WebrtcReconnector(state, this.websocket, this.webrtc),
|
webrtc: new Reconnector(new WebrtcReconnector(state, this.websocket, this.webrtc), state.webrtc.config),
|
||||||
state.webrtc.config,
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// websocket
|
// websocket
|
||||||
this._websocket_reconn.on('connect', () => {
|
this._reconnector.websocket.on('connect', () => {
|
||||||
if (this.websocket.connected && this.webrtc.connected) {
|
if (this.websocket.connected && this.webrtc.connected) {
|
||||||
Vue.set(this._state, 'status', 'connected')
|
Vue.set(this._state, 'status', 'connected')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.webrtc.connected) {
|
if (!this.webrtc.connected) {
|
||||||
this._webrtc_reconn.connect()
|
this._reconnector.webrtc.connect()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this._websocket_reconn.on('disconnect', () => {
|
this._reconnector.websocket.on('disconnect', () => {
|
||||||
if (this._state.status === 'connected' && this.activated) {
|
if (this._state.status === 'connected' && this.activated) {
|
||||||
Vue.set(this._state, 'status', 'connecting')
|
Vue.set(this._state, 'status', 'connecting')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this._websocket_reconn.on('close', (error) => {
|
this._reconnector.websocket.on('close', this.close.bind(this))
|
||||||
this.disconnect(error)
|
|
||||||
})
|
|
||||||
|
|
||||||
// webrtc
|
// webrtc
|
||||||
this._webrtc_reconn.on('connect', () => {
|
this._reconnector.webrtc.on('connect', () => {
|
||||||
if (this.websocket.connected && this.webrtc.connected) {
|
if (this.websocket.connected && this.webrtc.connected) {
|
||||||
Vue.set(this._state, 'status', 'connected')
|
Vue.set(this._state, 'status', 'connected')
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.set(this._state, 'type', 'webrtc')
|
Vue.set(this._state, 'type', 'webrtc')
|
||||||
})
|
})
|
||||||
this._webrtc_reconn.on('disconnect', () => {
|
this._reconnector.webrtc.on('disconnect', () => {
|
||||||
if (this._state.status === 'connected' && this.activated) {
|
if (this._state.status === 'connected' && this.activated) {
|
||||||
Vue.set(this._state, 'status', 'connecting')
|
Vue.set(this._state, 'status', 'connecting')
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.set(this._state, 'type', 'fallback')
|
Vue.set(this._state, 'type', 'fallback')
|
||||||
})
|
})
|
||||||
this._webrtc_reconn.on('close', (error) => {
|
this._reconnector.webrtc.on('close', this.close.bind(this))
|
||||||
this.disconnect(error)
|
|
||||||
})
|
|
||||||
|
|
||||||
let webrtcCongestion: number = 0
|
let webrtcCongestion: number = 0
|
||||||
this.webrtc.on('stats', (stats: WebRTCStats) => {
|
this.webrtc.on('stats', (stats: WebRTCStats) => {
|
||||||
Vue.set(this._state.webrtc, 'stats', stats)
|
Vue.set(this._state.webrtc, 'stats', stats)
|
||||||
|
|
||||||
// if automatic quality adjusting is turned off
|
// if automatic quality adjusting is turned off
|
||||||
if (!this._state.webrtc.auto || !this._webrtc_reconn.isOpen) return
|
if (!this._state.webrtc.auto || !this._reconnector.webrtc.isOpen) return
|
||||||
|
|
||||||
// if there are no or just one quality, no switching can be done
|
// if there are no or just one quality, no switching can be done
|
||||||
if (this._state.webrtc.videos.length <= 1) return
|
if (this._state.webrtc.videos.length <= 1) return
|
||||||
@ -118,14 +115,15 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to reconnect
|
// try to reconnect webrtc
|
||||||
this._webrtc_reconn.reconnect()
|
this._reconnector.webrtc.reconnect()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public get activated() {
|
public get activated() {
|
||||||
return this._websocket_reconn.isOpen && this._webrtc_reconn.isOpen
|
// check if every reconnecter is open
|
||||||
|
return Object.values(this._reconnector).every((r) => r.isOpen)
|
||||||
}
|
}
|
||||||
|
|
||||||
public setVideo(video: string) {
|
public setVideo(video: string) {
|
||||||
@ -136,7 +134,7 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
|||||||
this.websocket.send(EVENT.SIGNAL_VIDEO, { video })
|
this.websocket.send(EVENT.SIGNAL_VIDEO, { video })
|
||||||
}
|
}
|
||||||
|
|
||||||
public connect(video?: string) {
|
public open(video?: string) {
|
||||||
if (video) {
|
if (video) {
|
||||||
if (!this._state.webrtc.videos.includes(video)) {
|
if (!this._state.webrtc.videos.includes(video)) {
|
||||||
throw new Error('video id not found')
|
throw new Error('video id not found')
|
||||||
@ -148,23 +146,27 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
|
|||||||
Vue.set(this._state, 'type', 'fallback')
|
Vue.set(this._state, 'type', 'fallback')
|
||||||
Vue.set(this._state, 'status', 'connecting')
|
Vue.set(this._state, 'status', 'connecting')
|
||||||
|
|
||||||
this._webrtc_reconn.open(true)
|
// open all reconnecters
|
||||||
this._websocket_reconn.open()
|
Object.values(this._reconnector).forEach((r) => r.open(true))
|
||||||
|
|
||||||
|
this._reconnector.websocket.connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
public disconnect(error?: Error) {
|
public close(error?: Error) {
|
||||||
this._websocket_reconn.close()
|
if (this.activated) {
|
||||||
this._webrtc_reconn.close()
|
Vue.set(this._state, 'type', 'none')
|
||||||
|
Vue.set(this._state, 'status', 'disconnected')
|
||||||
|
|
||||||
Vue.set(this._state, 'type', 'none')
|
this.emit('close', error)
|
||||||
Vue.set(this._state, 'status', 'disconnected')
|
}
|
||||||
|
|
||||||
this.emit('disconnect', error)
|
// close all reconnecters
|
||||||
|
Object.values(this._reconnector).forEach((r) => r.close())
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy() {
|
public destroy() {
|
||||||
this._websocket_reconn.destroy()
|
// destroy all reconnecters
|
||||||
this._webrtc_reconn.destroy()
|
Object.values(this._reconnector).forEach((r) => r.destroy())
|
||||||
|
|
||||||
Vue.set(this._state, 'type', 'none')
|
Vue.set(this._state, 'type', 'none')
|
||||||
Vue.set(this._state, 'status', 'disconnected')
|
Vue.set(this._state, 'status', 'disconnected')
|
||||||
|
@ -12,7 +12,7 @@ export interface NekoEvents {
|
|||||||
['connection.status']: (status: 'connected' | 'connecting' | 'disconnected') => void
|
['connection.status']: (status: 'connected' | 'connecting' | 'disconnected') => void
|
||||||
['connection.webrtc.sdp']: (type: 'local' | 'remote', data: string) => void
|
['connection.webrtc.sdp']: (type: 'local' | 'remote', data: string) => void
|
||||||
['connection.webrtc.sdp.candidate']: (type: 'local' | 'remote', data: RTCIceCandidateInit) => void
|
['connection.webrtc.sdp.candidate']: (type: 'local' | 'remote', data: RTCIceCandidateInit) => void
|
||||||
['connection.disconnect']: (message: string) => void
|
['connection.closed']: (error?: Error) => void
|
||||||
|
|
||||||
// drag and drop events
|
// drag and drop events
|
||||||
['upload.drop.started']: () => void
|
['upload.drop.started']: () => void
|
||||||
@ -106,8 +106,7 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
|
|||||||
|
|
||||||
protected [EVENT.SYSTEM_DISCONNECT]({ message }: message.SystemDisconnect) {
|
protected [EVENT.SYSTEM_DISCONNECT]({ message }: message.SystemDisconnect) {
|
||||||
this._log.debug('EVENT.SYSTEM_DISCONNECT')
|
this._log.debug('EVENT.SYSTEM_DISCONNECT')
|
||||||
this._connection.disconnect()
|
this._connection.close(new Error(message))
|
||||||
this.emit('connection.disconnect', message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
@ -198,9 +198,9 @@
|
|||||||
this.api.setUrl(httpURL)
|
this.api.setUrl(httpURL)
|
||||||
Vue.set(this.state.connection, 'url', httpURL)
|
Vue.set(this.state.connection, 'url', httpURL)
|
||||||
|
|
||||||
if (this.connected) {
|
try {
|
||||||
this.connection.disconnect()
|
this.disconnect()
|
||||||
}
|
} catch (e) {}
|
||||||
|
|
||||||
if (this.state.authenticated) {
|
if (this.state.authenticated) {
|
||||||
Vue.set(this.state, 'authenticated', false)
|
Vue.set(this.state, 'authenticated', false)
|
||||||
@ -254,9 +254,9 @@
|
|||||||
throw new Error('client not authenticated')
|
throw new Error('client not authenticated')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.connected) {
|
try {
|
||||||
this.connection.disconnect()
|
this.disconnect()
|
||||||
}
|
} catch (e) {}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.api.session.logout()
|
await this.api.session.logout()
|
||||||
@ -281,7 +281,7 @@
|
|||||||
throw new Error('client is already connected')
|
throw new Error('client is already connected')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connection.connect(video)
|
this.connection.open(video)
|
||||||
}
|
}
|
||||||
|
|
||||||
public disconnect() {
|
public disconnect() {
|
||||||
@ -289,7 +289,7 @@
|
|||||||
throw new Error('client is not connected')
|
throw new Error('client is not connected')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connection.disconnect()
|
this.connection.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
public play() {
|
public play() {
|
||||||
@ -383,7 +383,8 @@
|
|||||||
// video events
|
// video events
|
||||||
VideoRegister(this._video, this.state.video)
|
VideoRegister(this._video, this.state.video)
|
||||||
|
|
||||||
this.connection.on('disconnect', () => {
|
this.connection.on('close', (error) => {
|
||||||
|
this.events.emit('connection.closed', error)
|
||||||
this.clear()
|
this.clear()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user