mancala/src/rtmt/rtmt_websocket.ts

129 lines
3.9 KiB
TypeScript
Raw Normal View History

2021-06-27 19:28:09 +03:00
import { decode, encode } from "./encode_decode_message"
import { Bytes, OnMessage, RTMT } from "./rtmt"
import WebSocket from "ws"
import * as http from 'http';
2022-07-16 18:46:04 +03:00
import { channel_ping, channel_pong } from "../consts/channel_names";
const PING_INTERVAL = 1000;
2021-06-27 19:28:09 +03:00
export class RTMTWS implements RTMT {
private messageChannels: Map<String, OnMessage>
private wsServer: WebSocket.Server | null
public clients = new Map<string, WebSocket>()
2022-07-16 18:46:04 +03:00
private pingInterval?: NodeJS.Timeout = undefined;
2021-06-27 19:28:09 +03:00
constructor() {
this.messageChannels = new Map<String, OnMessage>()
this.wsServer = null
}
2022-07-16 18:46:04 +03:00
initWebSocket(server: http.Server, onopen: (userKey: string) => any) {
2021-06-27 19:28:09 +03:00
const wsServer = new WebSocket.Server({ server })
2021-06-29 03:25:42 +03:00
this.wsServer = wsServer
2021-06-27 19:28:09 +03:00
this.clients = new Map<string, WebSocket>()
wsServer.on("connection", (ws: WebSocket, req: Request) => {
2022-07-16 18:46:04 +03:00
console.log("Client Connected");
2021-06-27 19:28:09 +03:00
const regexResult = req.url.split(RegExp("\/\?userKey="));
const clientID = regexResult[1]
this.clients.set(clientID, ws)
2022-04-23 12:54:56 +03:00
ws.on("message", (messageBytes: string) => {
2021-06-29 03:25:42 +03:00
this.onWebSocketMessage(clientID, messageBytes)
2021-06-27 19:28:09 +03:00
})
ws.on("close", (code: number, reason: string) => {
console.log("WS Closed! code : " + code + " reason : " + reason);
this.clients.delete(clientID)
})
ws.on("error", (err: Error) => {
console.log("WS Closed with error! error : " + err.message);
this.clients.delete(clientID)
})
2021-06-29 03:25:42 +03:00
2022-07-16 18:46:04 +03:00
this.setWebSocketAsAlive(ws);
2021-06-29 03:25:42 +03:00
onopen(clientID)
2021-06-27 19:28:09 +03:00
})
2022-07-16 18:46:04 +03:00
this.startPingInterval(wsServer);
}
2021-06-27 19:28:09 +03:00
2022-07-16 18:46:04 +03:00
dispose() {
this.stopPingInterval();
2021-06-27 19:28:09 +03:00
}
2022-04-23 12:54:56 +03:00
sendMessage(clientID: string, channel: string, message: Object) {
2021-06-27 19:28:09 +03:00
if (this.wsServer) {
const client = this.clients.get(clientID)
if (client) {
2022-07-16 18:46:04 +03:00
this.sendMessageInternal(client, channel, message);
2021-06-27 19:28:09 +03:00
} else {
console.log("Client not connected!");
}
} else {
console.log('ws is undefined')
}
}
2022-07-16 18:46:04 +03:00
sendMessageInternal(ws: WebSocket, channel: string, message: Object) {
const data = encode({ channel: channel, message: message })
ws.send(data)
}
2021-06-27 19:28:09 +03:00
listenMessage(channel: string, callback: OnMessage) {
this.messageChannels.set(channel, callback)
}
2022-04-23 12:54:56 +03:00
onWebSocketMessage(clientID: string, messageBytes: string) {
2021-06-27 19:28:09 +03:00
const message = decode(messageBytes)
2022-04-23 12:54:56 +03:00
this.onMessage(clientID, message.channel, message.message)
2021-06-27 19:28:09 +03:00
}
2022-04-23 12:54:56 +03:00
onMessage(clientID: string, channel: string, message: Object) {
2022-07-16 18:46:04 +03:00
if (channel === channel_pong) {
const ws = this.clients.get(clientID);
if (ws) {
this.heartbeat(ws);
}
return;
}
2021-06-27 19:28:09 +03:00
const callback = this.messageChannels.get(channel)
if (callback) {
callback(clientID, message)
} else {
console.log("Channel callback not found! " + channel);
}
}
2022-07-16 18:46:04 +03:00
startPingInterval(wsServer: WebSocket.Server) {
this.stopPingInterval();
this.pingInterval = setInterval(() => {
const sendMessageInternal = this.sendMessageInternal;
wsServer.clients.forEach(function each(ws) {
//@ts-ignore
if (ws.isAlive === false) return ws.terminate();
//@ts-ignore
ws.isAlive = false;
sendMessageInternal(ws, channel_ping, {});
});
}, PING_INTERVAL);
}
stopPingInterval() {
if (this.pingInterval) clearInterval(this.pingInterval);
}
heartbeat(ws: WebSocket) {
this.setWebSocketAsAlive(ws);
}
setWebSocketAsAlive(ws: WebSocket) {
//@ts-ignore
ws.isAlive = true;
}
2021-06-27 19:28:09 +03:00
}