diff --git a/scripts/WhiteboardServerSideInfo.js b/scripts/WhiteboardServerSideInfo.js deleted file mode 100644 index 712eb64..0000000 --- a/scripts/WhiteboardServerSideInfo.js +++ /dev/null @@ -1,106 +0,0 @@ -const config = require("./config/config"); - -/** - * Class to hold information related to a whiteboard - */ -class WhiteboardServerSideInfo { - static defaultScreenResolution = { w: 1000, h: 1000 }; - - /** - * @type {number} - * @private - */ - #nbConnectedUsers = 0; - get nbConnectedUsers() { - return this.#nbConnectedUsers; - } - - /** - * @type {Map} - * @private - */ - #screenResolutionByClients = new Map(); - get screenResolutionByClients() { - return this.#screenResolutionByClients; - } - - /** - * Variable to tell if these info have been sent or not - * - * @private - * @type {boolean} - */ - #hasNonSentUpdates = false; - get hasNonSentUpdates() { - return this.#hasNonSentUpdates; - } - - incrementNbConnectedUsers() { - this.#nbConnectedUsers++; - this.#hasNonSentUpdates = true; - } - - decrementNbConnectedUsers() { - this.#nbConnectedUsers--; - this.#hasNonSentUpdates = true; - } - - hasConnectedUser() { - return this.#nbConnectedUsers > 0; - } - - /** - * Store information about the client's screen resolution - * - * @param {number} clientId - * @param {number} w client's width - * @param {number} h client's hight - */ - setScreenResolutionForClient(clientId, { w, h }) { - this.#screenResolutionByClients.set(clientId, { w, h }); - this.#hasNonSentUpdates = true; - } - - /** - * Delete the stored information about the client's screen resoltion - * @param clientId - */ - deleteScreenResolutionOfClient(clientId) { - this.#screenResolutionByClients.delete(clientId); - this.#hasNonSentUpdates = true; - } - - /** - * Get the smallest client's screen size on a whiteboard - * @return {{w: number, h: number}} - */ - getSmallestScreenResolution() { - const { screenResolutionByClients: resolutions } = this; - return { - w: Math.min(...Array.from(resolutions.values()).map((res) => res.w)), - h: Math.min(...Array.from(resolutions.values()).map((res) => res.h)), - }; - } - - infoWasSent() { - this.#hasNonSentUpdates = false; - } - - shouldSendInfo() { - return this.#hasNonSentUpdates; - } - - asObject() { - const out = { - nbConnectedUsers: this.#nbConnectedUsers, - }; - - if (config.frontend.showSmallestScreenIndicator) { - out.smallestScreenResolution = this.getSmallestScreenResolution(); - } - - return out; - } -} - -module.exports = WhiteboardServerSideInfo; diff --git a/scripts/server-backend.js b/scripts/server-backend.js index a5b4e4d..fc9c653 100644 --- a/scripts/server-backend.js +++ b/scripts/server-backend.js @@ -1,8 +1,8 @@ const path = require("path"); const config = require("./config/config"); -const WhiteboardServerSideInfo = require("./WhiteboardServerSideInfo"); const ReadOnlyBackendService = require("./services/ReadOnlyBackendService"); +const WhiteboardInfoBackendService = require("./services/WhiteboardInfoBackendService"); function startBackendServer(port) { var fs = require("fs-extra"); @@ -24,6 +24,8 @@ function startBackendServer(port) { var server = require("http").Server(app); server.listen(port); var io = require("socket.io")(server, { path: "/ws-api" }); + WhiteboardInfoBackendService.start(io); + console.log("Webserver & socketserver running on port:" + port); const { accessToken, enableWebdav } = config.backend; @@ -180,41 +182,11 @@ function startBackendServer(port) { } } - /** - * @type {Map} - */ - const infoByWhiteboard = new Map(); - - setInterval(() => { - infoByWhiteboard.forEach((info, whiteboardId) => { - if (info.shouldSendInfo()) { - io.sockets - .in(whiteboardId) - .compress(false) - .emit("whiteboardInfoUpdate", info.asObject()); - info.infoWasSent(); - } - }); - }, (1 / config.backend.performance.whiteboardInfoBroadcastFreq) * 1000); - io.on("connection", function (socket) { let whiteboardId = null; socket.on("disconnect", function () { - if (infoByWhiteboard.has(whiteboardId)) { - const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId); - - if (socket && socket.id) { - whiteboardServerSideInfo.deleteScreenResolutionOfClient(socket.id); - } - - whiteboardServerSideInfo.decrementNbConnectedUsers(); - - if (whiteboardServerSideInfo.hasConnectedUser()) { - socket.compress(false).broadcast.emit("refreshUserBadges", null); //Removes old user Badges - } else { - infoByWhiteboard.delete(whiteboardId); - } - } + WhiteboardInfoBackendService.disconnect(socket.id, whiteboardId); + socket.compress(false).broadcast.to(whiteboardId).emit("refreshUserBadges", null); //Removes old user Badges }); socket.on("drawToWhiteboard", function (content) { @@ -226,12 +198,9 @@ function startBackendServer(port) { socket.compress(false).broadcast.to(wid).emit("drawToWhiteboard", content); // broadcast to current whiteboard broadcastTo(whiteboardId); + // broadcast the same content to the associated read-only whiteboard const readOnlyId = ReadOnlyBackendService.getReadOnlyId(whiteboardId); - const readOnlyWhiteboardInfo = infoByWhiteboard.get(readOnlyId); - if (readOnlyWhiteboardInfo && readOnlyWhiteboardInfo.hasConnectedUser()) { - // broadcast the same content to the associated read-only whiteboard - broadcastTo(readOnlyId); - } + broadcastTo(readOnlyId); s_whiteboard.handleEventsAndData(content); //save whiteboardchanges on the server } else { socket.emit("wrongAccessToken", true); @@ -254,16 +223,8 @@ function startBackendServer(port) { }); socket.join(whiteboardId); //Joins room name=wid - if (!infoByWhiteboard.has(whiteboardId)) { - infoByWhiteboard.set(whiteboardId, new WhiteboardServerSideInfo()); - } - - const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId); - whiteboardServerSideInfo.incrementNbConnectedUsers(); - whiteboardServerSideInfo.setScreenResolutionForClient( - socket.id, - content["windowWidthHeight"] || WhiteboardServerSideInfo.defaultScreenResolution - ); + const screenResolution = content["windowWidthHeight"]; + WhiteboardInfoBackendService.join(socket.id, whiteboardId, screenResolution); } else { socket.emit("wrongAccessToken", true); } @@ -272,10 +233,11 @@ function startBackendServer(port) { socket.on("updateScreenResolution", function (content) { content = escapeAllContentStrings(content); if (accessToken === "" || accessToken == content["at"]) { - const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId); - whiteboardServerSideInfo.setScreenResolutionForClient( + const screenResolution = content["windowWidthHeight"]; + WhiteboardInfoBackendService.setScreenResolution( socket.id, - content["windowWidthHeight"] || WhiteboardServerSideInfo.defaultScreenResolution + whiteboardId, + screenResolution ); } }); diff --git a/scripts/services/WhiteboardInfoBackendService.js b/scripts/services/WhiteboardInfoBackendService.js new file mode 100644 index 0000000..98d17d3 --- /dev/null +++ b/scripts/services/WhiteboardInfoBackendService.js @@ -0,0 +1,194 @@ +const config = require("../config/config"); + +/** + * Class to hold information related to a whiteboard + */ +class WhiteboardInfo { + static defaultScreenResolution = { w: 1000, h: 1000 }; + + /** + * @type {number} + * @private + */ + #nbConnectedUsers = 0; + get nbConnectedUsers() { + return this.#nbConnectedUsers; + } + + /** + * @type {Map} + * @private + */ + #screenResolutionByClients = new Map(); + get screenResolutionByClients() { + return this.#screenResolutionByClients; + } + + /** + * Variable to tell if these info have been sent or not + * + * @private + * @type {boolean} + */ + #hasNonSentUpdates = false; + get hasNonSentUpdates() { + return this.#hasNonSentUpdates; + } + + incrementNbConnectedUsers() { + this.#nbConnectedUsers++; + this.#hasNonSentUpdates = true; + } + + decrementNbConnectedUsers() { + this.#nbConnectedUsers--; + this.#hasNonSentUpdates = true; + } + + hasConnectedUser() { + return this.#nbConnectedUsers > 0; + } + + /** + * Store information about the client's screen resolution + * + * @param {string} clientId + * @param {number} w client's width + * @param {number} h client's hight + */ + setScreenResolutionForClient(clientId, { w, h }) { + this.#screenResolutionByClients.set(clientId, { w, h }); + this.#hasNonSentUpdates = true; + } + + /** + * Delete the stored information about the client's screen resoltion + * @param clientId + */ + deleteScreenResolutionOfClient(clientId) { + this.#screenResolutionByClients.delete(clientId); + this.#hasNonSentUpdates = true; + } + + /** + * Get the smallest client's screen size on a whiteboard + * @return {{w: number, h: number}} + */ + getSmallestScreenResolution() { + const { screenResolutionByClients: resolutions } = this; + return { + w: Math.min(...Array.from(resolutions.values()).map((res) => res.w)), + h: Math.min(...Array.from(resolutions.values()).map((res) => res.h)), + }; + } + + infoWasSent() { + this.#hasNonSentUpdates = false; + } + + shouldSendInfo() { + return this.#hasNonSentUpdates; + } + + asObject() { + const out = { + nbConnectedUsers: this.#nbConnectedUsers, + }; + + if (config.frontend.showSmallestScreenIndicator) { + out.smallestScreenResolution = this.getSmallestScreenResolution(); + } + + return out; + } +} + +class WhiteboardInfoBackendService { + /** + * @type {Map} + */ + #infoByWhiteboard = new Map(); + + /** + * Start the auto sending of information to all the whiteboards + * + * @param io + */ + start(io) { + // auto clean infoByWhiteboard + setInterval(() => { + this.#infoByWhiteboard.forEach((info, whiteboardId) => { + if (info.shouldSendInfo()) { + io.sockets + .in(whiteboardId) + .compress(false) + .emit("whiteboardInfoUpdate", info.asObject()); + info.infoWasSent(); + } + }); + }, (1 / config.backend.performance.whiteboardInfoBroadcastFreq) * 1000); + } + + /** + * Track a join event of client to a whiteboard + * + * @param {string} clientId + * @param {string} whiteboardId + * @param {{w: number, h: number}} screenResolution + */ + join(clientId, whiteboardId, screenResolution) { + const infoByWhiteboard = this.#infoByWhiteboard; + + if (!infoByWhiteboard.has(whiteboardId)) { + infoByWhiteboard.set(whiteboardId, new WhiteboardInfo()); + } + + const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId); + whiteboardServerSideInfo.incrementNbConnectedUsers(); + this.setScreenResolution(clientId, whiteboardId, screenResolution); + } + + /** + * Set the screen resolution of a client + * @param {string} clientId + * @param {string} whiteboardId + * @param {{w: number, h: number}} screenResolution + */ + setScreenResolution(clientId, whiteboardId, screenResolution) { + const infoByWhiteboard = this.#infoByWhiteboard; + + const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId); + if (whiteboardServerSideInfo) { + whiteboardServerSideInfo.setScreenResolutionForClient( + clientId, + screenResolution || WhiteboardInfo.defaultScreenResolution + ); + } + } + + /** + * Track disconnect from a client + * @param {string} clientId + * @param {string} whiteboardId + */ + disconnect(clientId, whiteboardId) { + const infoByWhiteboard = this.#infoByWhiteboard; + + if (infoByWhiteboard.has(whiteboardId)) { + const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId); + + if (clientId) { + whiteboardServerSideInfo.deleteScreenResolutionOfClient(clientId); + } + + whiteboardServerSideInfo.decrementNbConnectedUsers(); + + if (whiteboardServerSideInfo.hasConnectedUser()) { + } else { + infoByWhiteboard.delete(whiteboardId); + } + } + } +} + +module.exports = new WhiteboardInfoBackendService();