js server comments

main
km0 2 years ago
parent f3507a5e87
commit 85890a32c1

@ -1,13 +1,21 @@
// Import dependencies
const { WebSocket, WebSocketServer } = require("ws"); const { WebSocket, WebSocketServer } = require("ws");
const express = require("express");
const dotenv = require("dotenv"); const dotenv = require("dotenv");
dotenv.config(); dotenv.config();
const express = require("express"); // Setup Environmental Variables
const PORT = process.env.PORT || 3000; const PORT = process.env.PORT || 3000;
const PREFIX = process.env.PREFIX || ""; const PREFIX = process.env.PREFIX || "";
const PUBLIC = process.env.PUBLIC || ""; const PUBLIC = process.env.PUBLIC || "";
// Setup Express Router
// Create the routes of the application
// Here are two pages and a wildcard:
// at / there is the index.html page, where to draw
// at /destination there is the destination.html page, where to receive the drawings
// the wildcard /* serves the static files from the public folder
const router = express.Router(); const router = express.Router();
const routes = (app) => { const routes = (app) => {
app.get("/", (req, res) => { app.get("/", (req, res) => {
@ -26,6 +34,7 @@ const routes = (app) => {
return app; return app;
}; };
// Setup the Express server
const server = express() const server = express()
.set("view engine", "html") .set("view engine", "html")
.engine("html", require("hbs").__express) .engine("html", require("hbs").__express)
@ -33,12 +42,19 @@ const server = express()
.use(express.static("public")) .use(express.static("public"))
.listen(PORT, () => console.log(`Listening on ${PORT}`)); .listen(PORT, () => console.log(`Listening on ${PORT}`));
// Setup the Websocket server on top of the Express one
const wss = new WebSocketServer({ server, clientTracking: true }); const wss = new WebSocketServer({ server, clientTracking: true });
// Global variables to manage the connected Destination and User clients
let DESTINATIONS = new Set(); let DESTINATIONS = new Set();
let USERS = new Set(); let USERS = new Set();
var theme = ""; var theme = "";
// The message processor defines which function is associated to every websocket message type.
// It map a type to a function, passing some optional parameters such as the message itself and the websocket client that sent it.
// for example an incoming message like {type: hello} will trigger the registerDest(ws, msg) function.
// In this way to add message types and functionalities gets easier, and avoid long chain of if-else statements.
const messageProcessor = { const messageProcessor = {
default: (ws, msg) => unknownMsg(msg), default: (ws, msg) => unknownMsg(msg),
hello: (ws, msg) => registerDest(ws, msg), hello: (ws, msg) => registerDest(ws, msg),
@ -46,11 +62,16 @@ const messageProcessor = {
theme: (ws, msg) => ((theme = msg.theme), broadcast(msg)), theme: (ws, msg) => ((theme = msg.theme), broadcast(msg)),
}; };
// Message processor functions
// Default function, to cactch unkown message types
const unknownMsg = (msg) => { const unknownMsg = (msg) => {
console.log("Unknown message type..."); console.log("Unknown message type...");
console.log(msg); console.log(msg);
}; };
// Add the ws client in the destinations set
// Removing it when it disconnets
const registerDest = (ws, msg) => { const registerDest = (ws, msg) => {
console.log("Destination client connected"); console.log("Destination client connected");
DESTINATIONS.add(ws); DESTINATIONS.add(ws);
@ -59,14 +80,17 @@ const registerDest = (ws, msg) => {
}); });
}; };
// Send a message to all the connected Destinations
const toDest = (msg) => { const toDest = (msg) => {
let message = JSON.stringify(msg);
DESTINATIONS.forEach((DESTINATION) => { DESTINATIONS.forEach((DESTINATION) => {
if (DESTINATION?.readyState === WebSocket.OPEN) { if (DESTINATION?.readyState === WebSocket.OPEN) {
DESTINATION.send(JSON.stringify(msg)); DESTINATION.send(message);
} }
}); });
}; };
// Send a message to all the connected Users
const broadcast = (msg) => { const broadcast = (msg) => {
let message = JSON.stringify(msg); let message = JSON.stringify(msg);
for (const user of USERS.values()) { for (const user of USERS.values()) {
@ -76,18 +100,21 @@ const broadcast = (msg) => {
} }
}; };
// Websocket events listener
wss.on("connection", (ws) => { wss.on("connection", (ws) => {
USERS.add(ws); USERS.add(ws);
ws.send(JSON.stringify({ type: "theme", theme: theme })); ws.send(JSON.stringify({ type: "theme", theme: theme }));
ws.on("message", (data) => { ws.on("message", (data) => {
// Parse the incoming data safely
let message; let message;
try { try {
message = JSON.parse(data); message = JSON.parse(data);
} catch (e) {} } catch (e) {}
// Call the message processor, eventually falling back to use the default function if the type is not defined.
if (message) { if (message) {
(messageProcessor[message.type] || messageProcessor.default)(ws, message); (messageProcessor[message?.type] || messageProcessor.default)(ws, message);
} }
}); });

Loading…
Cancel
Save