connection use data from state.

This commit is contained in:
Miroslav Šedivý 2021-07-17 15:17:56 +02:00
parent fdc7412afc
commit 368261ca14
3 changed files with 60 additions and 67 deletions

View File

@ -1,11 +1,10 @@
import Vue from 'vue' import Vue from 'vue'
import EventEmitter from 'eventemitter3' import EventEmitter from 'eventemitter3'
import { Logger } from '../utils/logger'
import * as EVENT from '../types/events' import * as EVENT from '../types/events'
import { NekoWebSocket } from './websocket' import { NekoWebSocket } from './websocket'
import { NekoWebRTC, WebRTCStats } from './webrtc' import { NekoWebRTC } from './webrtc'
import { Connection } from '../types/state' import { Connection, WebRTCStats } from '../types/state'
import { Reconnecter, ReconnecterAbstract } from '../utils/reconnecter' import { Reconnecter, ReconnecterAbstract } from '../utils/reconnecter'
const WEBRTC_RECONN_MAX_LOSS = 25 const WEBRTC_RECONN_MAX_LOSS = 25
@ -16,14 +15,13 @@ export interface NekoConnectionEvents {
} }
class WebsocketReconnecter extends ReconnecterAbstract { class WebsocketReconnecter extends ReconnecterAbstract {
private _conn: NekoConnection private _state: Connection
private _websocket: NekoWebSocket private _websocket: NekoWebSocket
constructor(conn: NekoConnection, websocket: NekoWebSocket) { constructor(state: Connection, websocket: NekoWebSocket) {
super() super()
// TODO: Antipattern. this._state = state
this._conn = conn
// TODO: Unmount. // TODO: Unmount.
this._websocket = websocket this._websocket = websocket
@ -32,8 +30,10 @@ class WebsocketReconnecter extends ReconnecterAbstract {
} }
public async connect() { public async connect() {
let url = this._conn.getUrl() let url = this._state.url
const token = this._conn.getToken() url = url.replace(/^http/, 'ws').replace(/\/+$/, '') + '/api/ws'
const token = this._state.token
if (token) { if (token) {
url += '?token=' + encodeURIComponent(token) url += '?token=' + encodeURIComponent(token)
} }
@ -47,15 +47,14 @@ class WebsocketReconnecter extends ReconnecterAbstract {
} }
class WebrtcReconnecter extends ReconnecterAbstract { class WebrtcReconnecter extends ReconnecterAbstract {
private _conn: NekoConnection private _state: Connection
private _websocket: NekoWebSocket private _websocket: NekoWebSocket
private _webrtc: NekoWebRTC private _webrtc: NekoWebRTC
constructor(conn: NekoConnection, websocket: NekoWebSocket, webrtc: NekoWebRTC) { constructor(state: Connection, websocket: NekoWebSocket, webrtc: NekoWebRTC) {
super() super()
// TODO: Antipattern. this._state = state
this._conn = conn
this._websocket = websocket this._websocket = websocket
// TODO: Unmount. // TODO: Unmount.
@ -65,7 +64,7 @@ class WebrtcReconnecter extends ReconnecterAbstract {
} }
public async connect() { public async connect() {
this._websocket.send(EVENT.SIGNAL_REQUEST, { video: this._conn.getVideo() }) this._websocket.send(EVENT.SIGNAL_REQUEST, { video: this._state.webrtc.video })
} }
public async disconnect() { public async disconnect() {
@ -74,31 +73,23 @@ class WebrtcReconnecter extends ReconnecterAbstract {
} }
export class NekoConnection extends EventEmitter<NekoConnectionEvents> { export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
private _url = ''
private _token = ''
private _video = ''
private _log = new Logger('connection')
private _state: Connection private _state: Connection
public websocket = new NekoWebSocket() public websocket = new NekoWebSocket()
public _websocket_reconn = new Reconnecter(new WebsocketReconnecter(this, this.websocket), { public _websocket_reconn: Reconnecter
max_reconnects: 15,
timeout_ms: 5000,
backoff_ms: 1500,
})
public webrtc = new NekoWebRTC() public webrtc = new NekoWebRTC()
public _webrtc_reconn = new Reconnecter(new WebrtcReconnecter(this, this.websocket, this.webrtc), { public _webrtc_reconn: Reconnecter
max_reconnects: 15,
timeout_ms: 10000,
backoff_ms: 1500,
})
constructor(state: Connection) { constructor(state: Connection) {
super() super()
this._state = state this._state = state
this._websocket_reconn = new Reconnecter(new WebsocketReconnecter(state, this.websocket), state.websocket.config)
this._webrtc_reconn = new Reconnecter(
new WebrtcReconnecter(state, this.websocket, this.webrtc),
state.webrtc.config,
)
// initial state // initial state
Vue.set(this._state, 'type', 'screencast') Vue.set(this._state, 'type', 'screencast')
@ -187,40 +178,22 @@ export class NekoConnection extends EventEmitter<NekoConnectionEvents> {
return this._websocket_reconn.isOpen && this._webrtc_reconn.isOpen return this._websocket_reconn.isOpen && this._webrtc_reconn.isOpen
} }
public setUrl(url: string) {
this._url = url.replace(/^http/, 'ws').replace(/\/+$/, '') + '/api/ws'
}
public getUrl(): string {
return this._url
}
public setToken(token: string) {
this._token = token
}
public getToken(): string {
return this._token
}
public setVideo(video: string) { public setVideo(video: string) {
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')
} }
if (this.websocket.connected) {
this.websocket.send(EVENT.SIGNAL_VIDEO, { video }) this.websocket.send(EVENT.SIGNAL_VIDEO, { video })
} }
this._video = video
}
public getVideo() {
return this._video
}
public async connect(video?: string): Promise<void> { public async connect(video?: string): Promise<void> {
if (video) this._video = video if (video) {
if (!this._state.webrtc.videos.includes(video)) {
throw new Error('video id not found')
}
Vue.set(this._state.webrtc, 'video', video)
}
this._webrtc_reconn.open(true) this._webrtc_reconn.open(true)
this._websocket_reconn.open() this._websocket_reconn.open()

View File

@ -110,8 +110,22 @@
public state = { public state = {
authenticated: false, authenticated: false,
connection: { connection: {
url: location.href,
token: undefined,
status: 'disconnected', status: 'disconnected',
websocket: {
config: {
maxReconnects: 15,
timeoutMs: 5000,
backoffMs: 1500,
},
},
webrtc: { webrtc: {
config: {
maxReconnects: 15,
timeoutMs: 10000,
backoffMs: 1500,
},
stats: null, stats: null,
video: null, video: null,
videos: [], videos: [],
@ -184,7 +198,7 @@
const httpURL = url.replace(/^ws/, 'http').replace(/\/$|\/ws\/?$/, '') const httpURL = url.replace(/^ws/, 'http').replace(/\/$|\/ws\/?$/, '')
this.api.setUrl(httpURL) this.api.setUrl(httpURL)
this.connection.setUrl(httpURL) Vue.set(this.state.connection, 'url', httpURL)
if (this.connected) { if (this.connected) {
this.connection.disconnect() this.connection.disconnect()
@ -208,7 +222,7 @@
if (token) { if (token) {
this.api.setToken(token) this.api.setToken(token)
this.connection.setToken(token) Vue.set(this.state.connection, 'token', token)
} }
await this.api.session.whoami() await this.api.session.whoami()
@ -227,7 +241,7 @@
const res = await this.api.session.login({ username, password }) const res = await this.api.session.login({ username, password })
if (res.data.token) { if (res.data.token) {
this.api.setToken(res.data.token) this.api.setToken(res.data.token)
this.connection.setToken(res.data.token) Vue.set(this.state.connection, 'token', res.data.token)
if (this.autologin) { if (this.autologin) {
localStorage.setItem('neko_session', res.data.token) localStorage.setItem('neko_session', res.data.token)
@ -250,7 +264,7 @@
await this.api.session.logout() await this.api.session.logout()
} finally { } finally {
this.api.setToken('') this.api.setToken('')
this.connection.setToken('') Vue.delete(this.state.connection, 'token')
if (this.autologin) { if (this.autologin) {
localStorage.removeItem('neko_session') localStorage.removeItem('neko_session')

View File

@ -1,3 +1,6 @@
import * as webrtcTypes from './webrtc'
import * as reconnecterTypes from './reconnecter'
export default interface State { export default interface State {
authenticated: boolean authenticated: boolean
connection: Connection connection: Connection
@ -13,27 +16,30 @@ export default interface State {
///////////////////////////// /////////////////////////////
export interface Connection { export interface Connection {
url: string
token?: string
status: 'disconnected' | 'connecting' | 'connected' status: 'disconnected' | 'connecting' | 'connected'
websocket: WebSocket
webrtc: WebRTC webrtc: WebRTC
screencast: boolean screencast: boolean
type: 'webrtc' | 'screencast' | 'none' type: 'webrtc' | 'screencast' | 'none'
} }
export interface WebSocket {
config: ReconnecterConfig
}
export interface WebRTC { export interface WebRTC {
config: ReconnecterConfig
stats: WebRTCStats | null stats: WebRTCStats | null
video: string | null video: string | null
videos: string[] videos: string[]
auto: boolean auto: boolean
} }
export interface WebRTCStats { export interface ReconnecterConfig extends reconnecterTypes.ReconnecterConfig {}
bitrate: number
packetLoss: number export interface WebRTCStats extends webrtcTypes.WebRTCStats {}
fps: number
width: number
height: number
muted?: boolean
}
///////////////////////////// /////////////////////////////
// Video // Video