// dtpweb-socket.js // Copyright (C) 2022,2023 DTP Technologies, LLC // All Rights Reserved 'use strict'; window.dtp = window.dtp || { }; // import UIkit from 'uikit'; import DtpWebLog from './dtp-log.js'; export default class DtpWebSocket { constructor ( ) { this.isConnected = false; this.isAuthenticated = false; this.joinedChannels = { }; this.log = new DtpWebLog('DtpWebSocket'); } async connect (options) { this.options = Object.assign({ mode: 'User', withRetry: true, withError: false, }, options); try { let buster = Math.random().toString().slice(2); let response; switch (this.options.mode) { case 'User': if (!window.dtp.user) { return false; // if we don't have a user, just go away and stop trying. } response = await fetch(`/auth/socket-token?cb=${buster}`); break; case 'Channel': response = await fetch(`/auth/socket-token/obs-widget?cb=${buster}`); break; } if (!response.ok) { if (options.withRetry) { return this.retryConnect(); } let json; try { json = await response.json(); } catch (jsonError) { throw new Error('socket failed to connect'); } throw new Error(`socket failed to connect: ${json.message}`); } const json = await response.json(); if (!json.success) { this.retryConnect(); throw new Error(`failed to connect: ${json.message}`); } this.log.debug('connect', 'WebSocket connecting to Digital Telepresence Platform', json); this.socket = io('/', { transports: ['websocket'], reconnection: false, auth: { token: json.token, }, }); this.socket.on('connect', this.onSocketConnect.bind(this)); this.socket.on('disconnect', this.onSocketDisconnect.bind(this)); this.socket.on('user-authenticated', this.onSocketUserAuthenticated.bind(this)); this.socket.on('widget-authenticated', this.onSocketWidgetAuthenticated.bind(this)); this.socket.on('join-result', this.onJoinResult.bind(this)); return true; } catch (error) { this.log.error('connect', 'failed to connect', { error }); if (this.options.withRetry) { this.retryConnect(); } if (this.options.withError) { throw error; } return false; } } async onSocketConnect ( ) { this.log.info('onSocketConnect', 'WebSocket connected'); this.isConnected = true; if (this.disconnectDialog) { this.disconnectDialog.hide(); delete this.disconnectDialog; } } async onSocketDisconnect (reason) { this.isConnected = false; this.socket.close(); if (this.options.onSocketDisconnect && (typeof this.options.onSocketDisconnect === 'function')) { this.options.onSocketDisconnect(this.socket); } delete this.socket; if (!this.isAuthenticated) { UIkit.modal.alert(`Failed to authenticate WebSocket session. Please log out, log back in, and try again.`); return; } this.log.warn('onSocketDisconnect', 'WebSocket disconnected', { reason }); this.showDisconnectWarning(reason); this.retryConnect(); } showDisconnectWarning (reason) { const REASONS = { 'io server disconnect': 'The server closed the connection', 'io client disconnect': 'The client closed the connection', 'ping timeout': 'The server is unreachable', 'transport close': 'Connection was lost or network changed', 'transport error': 'Server communication error, please try again.', }; const modal = UIkit.modal.dialog(`