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