From cd3912293fab2c66057bc50e933e884e498ba526 Mon Sep 17 00:00:00 2001 From: ari melody Date: Sun, 1 Oct 2023 19:31:32 +0100 Subject: [PATCH] WS pings to maintain connection, fixed server crash when sending malformed data --- public/index.html | 3 ++ public/scripts/main.js | 18 +++++++---- public/styles/main.css | 4 +-- server/main.js | 72 +++++++++++++++++++++++++++++++++++------- 4 files changed, 76 insertions(+), 21 deletions(-) diff --git a/public/index.html b/public/index.html index fe21d2a..d4bad3d 100644 --- a/public/index.html +++ b/public/index.html @@ -31,6 +31,9 @@ diff --git a/public/scripts/main.js b/public/scripts/main.js index ed8c3f6..2fdb154 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -11,12 +11,13 @@ var pre_buffer_chars = 0; var server_url = ""; const DATA_TYPES = { - text: 0, - colour: 1, - buffer: 2, - backspace: 3, - backword: 4, - arrow: 5, + ping: 0, + text: 1, + colour: 2, + buffer: 3, + backspace: 4, + backword: 5, + arrow: 6, }; function start() { @@ -108,6 +109,9 @@ function handle_message(data) { const is_at_bottom = content.scrollHeight - content.offsetHeight - content.scrollTop < 10; switch (data.type) { + case DATA_TYPES.ping: + client.send(JSON.stringify({type: DATA_TYPES.ping})); + break; case DATA_TYPES.colour: my_colour = data.colour; console.log(`%cColour has been changed to ${my_colour}`, `color: ${my_colour}`); @@ -253,7 +257,7 @@ function handle_paste(event) { type: DATA_TYPES.text, text: paste, }); - content.scrollTop = content.scrollHeight - content.offsetHeight - 28; + content.scrollTop = content.scrollHeight - content.offsetHeight; } const PALETTE = { diff --git a/public/styles/main.css b/public/styles/main.css index 4bb3630..88b8908 100644 --- a/public/styles/main.css +++ b/public/styles/main.css @@ -52,14 +52,14 @@ footer { display: flex; gap: 1em; align-items: center; + justify-content: space-between; } footer ul { - width: 100%; margin: 0; padding: 0; display: flex; - justify-content: space-between; + gap: 1em; } footer li { diff --git a/server/main.js b/server/main.js index 5b49896..d6dc248 100644 --- a/server/main.js +++ b/server/main.js @@ -21,12 +21,13 @@ const MIME_TYPES = { }; const DATA_TYPES = { - text: 0, - colour: 1, - buffer: 2, - backspace: 3, - backword: 4, - arrow: 5, + ping: 0, + text: 1, + colour: 2, + buffer: 3, + backspace: 4, + backword: 5, + arrow: 6, }; const MOTDS = [ @@ -46,16 +47,27 @@ const MOTDS = [ const STATIC_PATH = path.join(process.cwd(), "public"); -const banner = +const BANNER = `Welcome to OpenTerminal! `; +const FAKE_CRASH = +` + +========================================= +This copy of OpenTerminal is not genuine. +Please acquire a genuine copy. +This connection will now terminate. +========================================= +`; + const PORT = process.env.PORT || 8080; +const PING_INTERVAL = 10000; let sockets = []; let buffer = ""; -const MAX_BUFFER_SIZE = 10240; +const MAX_BUFFER_SIZE = 1024 * 1000; const MAX_MESSAGE_LENGTH = 1024; /** @@ -103,7 +115,7 @@ wss.on('connection', socket => { */ socket.send(JSON.stringify({ type: DATA_TYPES.text, - text: `${banner}/* ${MOTDS[Math.floor(Math.random() * MOTDS.length)]} */\n\n`, + text: `${BANNER}/* ${MOTDS[Math.floor(Math.random() * MOTDS.length)]} */\n\n`, colour: false, sticky: true, })); @@ -114,18 +126,40 @@ wss.on('connection', socket => { })); } + const ping_interval = setInterval( + function() { + socket.send(JSON.stringify({ + type: DATA_TYPES.ping, + })) + }, PING_INTERVAL); + socket.ping_interval = ping_interval; + sockets.push(socket); // console.log(`new connection.\n\tcurrent connections: ${sockets.length}`); - socket.on('message', event => { handle_message(JSON.parse(event), socket) }); + socket.on('message', event => { + try { + handle_message(JSON.parse(event), socket) + } catch (error) { + socket.send(JSON.stringify({ + type: DATA_TYPES.text, + text: FAKE_CRASH, + })); + console.error(error); + } + }); socket.on('close', () => { + clearInterval(socket.ping_interval); sockets = sockets.filter(s => s !== socket); // console.log(`connection closed.\n\tcurrent connections: ${sockets.length}`); }); }); +/** + * handles parsed JSON data sent by the client. + */ function handle_message(data, user) { switch (data.type) { case DATA_TYPES.backword: @@ -149,6 +183,11 @@ function handle_message(data, user) { return; } if (data.text.length > MAX_MESSAGE_LENGTH) { + user.send(JSON.stringify({ + type: DATA_TYPES.text, + text: "bleeeehhhh :P\n(message too long!)\n", + })) + user.close(); return; } block = { @@ -161,12 +200,15 @@ function handle_message(data, user) { } if (buffer.length > MAX_BUFFER_SIZE) { - send_as_server(`\n\nSERVER: This channel's maximum buffer length has been hit (${MAX_BUFFER_SIZE}).\n` + + broadcast_as_server(`\n\nSERVER: This channel's maximum buffer length has been hit (${MAX_BUFFER_SIZE}).\n` + `You will need to make more room, or the server will have to be restarted.\n` + `Apologies for the inconvenience!`) } } +/** + * generates a random hexadecimal colour value (ex. #ff00ff) + */ function generate_colour() { let result = '#'; let hexref = '0123456789abcdef'; @@ -180,7 +222,10 @@ server.listen(PORT, () => { console.log(`OpenTerminal is now LIVE on https://127.0.0.1:${PORT}!`); }); -function send_as_server(message) { +/** + * sends a server-wide message to all connected clients. + */ +function broadcast_as_server(message) { broadcast(JSON.stringify({ type: DATA_TYPES.text, text: message, @@ -188,6 +233,9 @@ function send_as_server(message) { })); } +/** + * sends raw data to all connected clients. + */ function broadcast(data) { sockets.forEach(s => s.send(data)); }