1
Fork 0
This repository has been archived on 2022-02-28. You can view files and clone it, but cannot push or open issues or pull requests.
web-drs-backend/server.node.ts

141 lines
3.6 KiB
TypeScript
Raw Normal View History

import * as fs from "fs";
import * as https from "https";
import { WebSocketServer } from "ws";
import * as crypto from "crypto";
2022-01-08 20:23:03 +01:00
import type {
AckMessage,
IdResponseMessage,
TextMessage,
2022-01-17 16:20:31 +01:00
TypingMessage,
2022-01-08 20:23:03 +01:00
} from "./lib/ServerMessage";
2022-01-07 17:36:19 +01:00
import {
2022-01-07 18:59:25 +01:00
isServerMessage,
isTextMessage,
2022-01-17 16:20:31 +01:00
isTypingMessage,
2022-01-07 18:59:25 +01:00
MessageType,
} from "./lib/ServerMessage";
const port = 8085;
2022-01-07 17:36:19 +01:00
const timeout = 15000;
2022-01-17 16:20:31 +01:00
const typingTimeout = 2000;
2022-01-07 17:36:19 +01:00
const httpsServer = https.createServer({
key: fs.readFileSync("./key.pem"),
cert: fs.readFileSync("./cert.pem"),
});
const webSocketServer = new WebSocketServer({ server: httpsServer });
2022-01-07 17:36:19 +01:00
2022-01-17 16:20:31 +01:00
/* If not using SSL/TLS
const webSocketServer = new WebSocketServer({ port });
*/
2022-01-07 17:36:19 +01:00
console.log("listening on port: " + port);
async function handleTextMessage(message: TextMessage, from: string) {
for (const to of webSocketServer.clients) {
to.send(
JSON.stringify(
Object.assign({}, message, {
author: from,
})
)
);
2022-01-07 17:36:19 +01:00
}
}
2022-01-07 17:36:19 +01:00
2022-01-17 16:20:31 +01:00
const activeConnections = new Set<string>();
const currentlyTyping = new Set<string>();
const currentlyTypingTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
async function handleTypingMessage(_message: TypingMessage, from: string) {
currentlyTyping.add(from);
if(currentlyTypingTimeouts.has(from)) {
clearTimeout(currentlyTypingTimeouts.get(from)!);
}
currentlyTypingTimeouts.set(from, setTimeout(() => {
currentlyTyping.delete(from);
currentlyTypingTimeouts.delete(from);
sendCurrentlyTypingMessage(from, true);
}, typingTimeout));
sendCurrentlyTypingMessage(from);
}
async function sendCurrentlyTypingMessage(from?: string, stopped = false) {
for (const to of webSocketServer.clients) {
to.send(
JSON.stringify(
Object.assign({
type: MessageType.CURRENTLY_TYPING,
date: Date.now(),
}, {
currently: Array.from(currentlyTyping.values()),
}, from === undefined ? {
__ctx: "regular update",
} : {
__ctx: from + (stopped ? " stopped typing" : " started typing"),
})
)
)
}
}
2022-01-08 20:23:03 +01:00
async function handleCloseConnection(id: string) {
activeConnections.delete(id);
}
webSocketServer.on("connection", function connection(socket) {
const close = (reason: string, code: number = 1000) => {
socket.send(
JSON.stringify({
type: MessageType.ACK,
date: Date.now(),
__ctx: `closing connection. reason: ${reason}`,
} as AckMessage)
);
socket.close(code, `closing connection. reason: ${reason}`);
2022-01-08 20:23:03 +01:00
handleCloseConnection(authorId);
};
2022-01-07 18:59:25 +01:00
2022-01-14 13:33:03 +01:00
const authorId: string = crypto.randomUUID();
socket.on("message", function (rawMessage: string) {
2022-01-07 18:59:25 +01:00
const message = JSON.parse(rawMessage);
if (!isServerMessage(message)) {
2022-01-14 13:33:03 +01:00
console.error(`Unexpected message received from client "${authorId}": \`${message}\``);
2022-01-08 20:23:03 +01:00
return;
2022-01-07 18:59:25 +01:00
}
2022-01-08 20:23:03 +01:00
2022-01-07 18:59:25 +01:00
if (isTextMessage(message)) {
2022-01-08 20:23:03 +01:00
if (message.author === authorId) {
handleTextMessage(message, authorId);
}
2022-01-17 16:20:31 +01:00
} else if (isTypingMessage(message)) {
handleTypingMessage(message, authorId);
2022-01-07 18:59:25 +01:00
}
2022-01-08 20:23:03 +01:00
2022-01-07 17:36:19 +01:00
clearTimeout(closeTimeout);
closeTimeout = setTimeout(close, timeout);
});
socket.on("close", function close() {
console.log("closed a connection");
});
2022-01-08 20:23:03 +01:00
console.log("new client connected! ID:", authorId);
socket.send(
JSON.stringify({
2022-01-08 20:23:03 +01:00
type: MessageType.ID_RESPONSE,
__ctx: "connected successfully",
2022-01-08 20:23:03 +01:00
date: Date.now(),
authorId,
} as IdResponseMessage)
);
2022-01-08 20:23:03 +01:00
activeConnections.add(authorId);
2022-01-07 17:36:19 +01:00
let closeTimeout = setTimeout(close, timeout);
});
httpsServer.listen(port);