import { EventEmitter } from 'eventemitter3'; import { Logging } from './api'; import { Revision } from './entities'; import { Call } from './types'; export class Connection { private log: Logging; private closed: boolean; private emitter: EventEmitter; private websocket: WebSocket; constructor(log: Logging, token: string, node: string, secure: boolean) { this.closed = false; this.log = log; this.emitter = new EventEmitter(); this.websocket = this.setWebSocket(token, node, secure); } public async close() { this.closed = true; if (this.websocket) { this.websocket.close(); } } public addRevisionListener(ev: (revision: Revision) => void): void { this.emitter.on('revision', ev); } public removeRevisionListener(ev: (revision: Revision) => void): void { this.emitter.off('revision', ev); } public addRingListener(ev: (call: Call) => void): void { this.emitter.on('call', ev); } public removeRingListener(ev: (call: Call) => void): void { this.emitter.off('call', ev); } public addStatusListener(ev: (status: string) => void): void { this.emitter.on('status', ev); } public removeStatusListener(ev: (status: string) => void): void { this.emitter.off('status', ev); } private setWebSocket(token: string, node: string, secure: boolean): WebSocket { if (this.closed) { this.emitter.emit('status', 'closed'); return this.websocket; } this.emitter.emit('status', 'connecting'); const wsUrl = `ws${secure ? 's' : ''}://${node}/status?mode=ring`; const ws = new WebSocket(wsUrl); ws.onmessage = (e) => { try { if (e.data === '') { this.close(); } const activity = JSON.parse(e.data); this.emitter.emit('status', 'connected'); if (activity.revision) { this.emitter.emit('revision', activity.revision as Revision); } else if (activity.ring) { const { cardId, callId, calleeToken, ice, iceUrl, iceUsername, icePassword } = activity.ring; const call: Call = { cardId, callId, calleeToken, ice: ice ? ice : [ { urls: iceUrl, username: iceUsername, credential: icePassword, }, ], }; this.emitter.emit('call', call); } else { this.emitter.emit('revision', activity as Revision); } } catch (err) { console.log(err); ws.close(); } }; ws.onclose = (e) => { console.log(e); this.emitter.emit('status', 'disconnected'); setTimeout(() => { if (ws != null) { ws.onmessage = () => {}; ws.onclose = () => {}; ws.onopen = () => {}; ws.onerror = () => {}; this.websocket = this.setWebSocket(token, node, secure); } }, 1000); }; ws.onopen = () => { ws.send(JSON.stringify({ AppToken: token })); }; ws.onerror = (e) => { console.log(e); ws.close(); }; return ws; } }