"use strict"; import WebSocket from 'ws'; import { backgroundMitt } from './emitter'; import { ipcMain } from "electron"; import { play } from './audio'; import { UserCreds, ClientMessage, RenderMessage, Annotation } from "@/types/message/index"; import { clientMessage, initRenderMessageFromString } from '@/modules/message'; import { v4 as uuidv4 } from 'uuid'; const ip = 'ws://127.0.0.1'; const port = 8760; const reconnectTimeout = 3000; //ms let socket: WebSocket; let success = false; let auth = false; const onAuthSession = async (e: any, payload: string | UserCreds | null): Promise => { return new Promise((resolve, reject) => { console.log('authenticating...'); backgroundMitt.once('auth-res', (res: string) => { if (res === 'locked') { reject(res); } else { console.log('Success!'); auth = true; resolve(res); } }); if (!payload) { socket.send('no-token'); } else if (payload instanceof String || typeof payload === 'string') { socket.send(payload); } else { socket.send(JSON.stringify(payload)); } }); }; const onMessage = (message_str: string): void => { while (!auth) { backgroundMitt.emit('auth-res', message_str); return; } // Decode the message. const m = JSON.parse(message_str) let message: RenderMessage | Annotation; // Check to see if this is a Render Message. if (m.content) { message = initRenderMessageFromString(message_str) // Play audio if any. if (message.content.audio) { const audioBytes = Buffer.from(m.content.audio as string, 'hex'); m.content.audio = true; play(audioBytes); } } else { message = m // Annotation } // Send it to the frontend. backgroundMitt.emit('ipc-renderer', { endpoint: 'render-message', message: message }); }; const onClientMessage = (e: any, payload: ClientMessage): void => { console.log('sending message'); socket.send(JSON.stringify(payload)); } const restart = () => { auth = false; initSession(); } // Run every time we want to connect to backend. export function initSession(): void { // Close existing sockets. if (socket) { socket.removeAllListeners(); socket.terminate(); socket.close(); success = false; } // Init new socket. socket = new WebSocket(`${ip}:${port}`); socket.binaryType = 'arraybuffer'; // handle renderer auth-token event ipcMain.removeHandler('auth-session'); // avoid setting duplicate handlers ipcMain.handle('auth-session', onAuthSession); // handle user message event ipcMain.removeAllListeners('client-message'); ipcMain.on('client-message', onClientMessage); // handle renderer logout event ipcMain.removeAllListeners('logout'); ipcMain.on('logout', (_event, _payload: string) => restart()); // Connect to the backend. socket.on('open', () => { console.log('Connected to Crimata Servers.'); // call auth renderer event on connection backgroundMitt.emit('ipc-renderer', { endpoint: 'auth', message: null }); success = true; }); // Handle for failed connect, try again. socket.on('error', (_e) => { console.log('ERROR: Failed to connect.'); socket.removeAllListeners(); socket.close(); setTimeout(() => { if (!success) { console.log('Reconnecting...'); initSession(); } }, reconnectTimeout); }); socket.on('close', () => { console.log('Connection droped! Restarting...'); restart(); }); socket.on("message", onMessage); } export function sendAudio(audio: string, uid: string): void { const m = clientMessage("", audio, uid); socket.send(JSON.stringify(m)); }