Commit | Line | Data |
---|---|---|
4198ad5c | 1 | import { Protocol, ProtocolCommand, ProtocolRequest, ProtocolVersion } from '../types/UIProtocol'; |
6a49ad23 | 2 | import WebSocket, { OPEN, Server, ServerOptions } from 'ws'; |
4198ad5c JB |
3 | |
4 | import AbstractUIService from './UIWebSocketServices/AbstractUIService'; | |
5 | import BaseError from '../exception/BaseError'; | |
6a49ad23 | 6 | import Configuration from '../utils/Configuration'; |
4198ad5c JB |
7 | import { IncomingMessage } from 'http'; |
8 | import UIServiceFactory from './UIWebSocketServices/UIServiceFactory'; | |
9 | import Utils from '../utils/Utils'; | |
4198ad5c JB |
10 | import logger from '../utils/Logger'; |
11 | ||
6a49ad23 | 12 | export default class UIWebSocketServer extends Server { |
4198ad5c JB |
13 | public uiService: AbstractUIService; |
14 | ||
6a49ad23 | 15 | public constructor(options?: ServerOptions, callback?: () => void) { |
4198ad5c | 16 | // Create the WebSocket Server |
6a49ad23 | 17 | super(options ?? Configuration.getUIWebSocketServer().options, callback); |
4198ad5c JB |
18 | } |
19 | ||
20 | public broadcastToClients(message: string | Record<string, unknown>): void { | |
21 | for (const client of this.clients) { | |
6a49ad23 | 22 | if (client?.readyState === OPEN) { |
4198ad5c JB |
23 | client.send(message); |
24 | } | |
25 | } | |
26 | } | |
27 | ||
28 | public start(): void { | |
29 | this.on('connection', (socket: WebSocket, request: IncomingMessage): void => { | |
30 | const protocolIndex = socket.protocol.indexOf(Protocol.UI); | |
31 | const version = socket.protocol.substring(protocolIndex + Protocol.UI.length) as ProtocolVersion; | |
32 | this.uiService = UIServiceFactory.getUIServiceImplementation(version, this); | |
33 | if (!this.uiService) { | |
410a760d | 34 | throw new BaseError(`Could not find a UI service implementation for UI protocol version ${version}`); |
4198ad5c JB |
35 | } |
36 | // FIXME: check connection validity | |
37 | socket.on('message', (messageData) => { | |
38 | let [command, payload]: ProtocolRequest = [ProtocolCommand.UNKNOWN, {}]; | |
39 | const protocolRequest = JSON.parse(messageData.toString()) as ProtocolRequest; | |
40 | if (Utils.isIterable(protocolRequest)) { | |
41 | [command, payload] = protocolRequest; | |
42 | } else { | |
410a760d | 43 | throw new BaseError('UI protocol request is not iterable'); |
4198ad5c JB |
44 | } |
45 | this.uiService.handleMessage(command, payload).catch(() => { | |
46 | logger.error(`${this.logPrefix()} Error while handling command %s message: %j`, command, payload); | |
47 | }); | |
48 | }); | |
49 | socket.on('error', (error) => { | |
50 | logger.error(`${this.logPrefix()} Error on WebSocket: %j`, error); | |
51 | }); | |
52 | }); | |
53 | } | |
54 | ||
55 | public stop(): void { | |
56 | this.close(); | |
57 | } | |
58 | ||
59 | public logPrefix(): string { | |
410a760d | 60 | return Utils.logPrefix(' UI WebSocket Server:'); |
4198ad5c JB |
61 | } |
62 | } |