aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authormarzavec <admin@marzavec.com>2018-06-03 20:08:35 +0200
committermarzavec <admin@marzavec.com>2018-06-03 20:08:35 +0200
commit62daa4893f374c1cbbecc63e4f1d4eec3fd29325 (patch)
treef5677c91c86efd60eb78d4c6b0258b17c1926074 /server
parentMerge pull request #16 from OpSimple/master (diff)
downloadhackchat-62daa4893f374c1cbbecc63e4f1d4eec3fd29325.tar.gz
hackchat-62daa4893f374c1cbbecc63e4f1d4eec3fd29325.zip
Completed protocol decoupling
Diffstat (limited to 'server')
-rw-r--r--server/package-lock.json100
-rw-r--r--server/package.json2
-rw-r--r--server/src/commands/core/chat.js1
-rw-r--r--server/src/commands/core/disconnect.js21
-rw-r--r--server/src/commands/core/ping.js12
-rw-r--r--server/src/commands/internal/disconnect.js30
-rw-r--r--server/src/commands/internal/socketreply.js22
-rw-r--r--server/src/commands/mod/dumb.js14
-rw-r--r--server/src/commands/mod/speak.js11
-rw-r--r--server/src/core/server.js16
-rw-r--r--server/src/managers/commands.js26
11 files changed, 155 insertions, 100 deletions
diff --git a/server/package-lock.json b/server/package-lock.json
index a709b1b..aa8283d 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -9,7 +9,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
- "color-convert": "1.9.1"
+ "color-convert": "^1.9.0"
}
},
"async": {
@@ -27,8 +27,8 @@
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
- "core-js": "2.5.6",
- "regenerator-runtime": "0.11.1"
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
}
},
"balanced-match": {
@@ -46,7 +46,7 @@
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
- "balanced-match": "1.0.0",
+ "balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
@@ -55,9 +55,9 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"requires": {
- "ansi-styles": "3.2.1",
- "escape-string-regexp": "1.0.5",
- "supports-color": "5.4.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
}
},
"color-convert": {
@@ -65,7 +65,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
"integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
"requires": {
- "color-name": "1.1.3"
+ "color-name": "^1.1.1"
}
},
"color-name": {
@@ -83,7 +83,7 @@
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.7.2.tgz",
"integrity": "sha512-joj9ZlUOjCrwdbmiLqafeUSgkUM74NqhLsZtSqDmhKudaIY197zTrb8JMl31fMnCUuxwFT23eC/oWvrZzDLRJQ==",
"requires": {
- "babel-runtime": "6.26.0"
+ "babel-runtime": "^6.26.0"
}
},
"concat-map": {
@@ -111,8 +111,8 @@
"resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.13.tgz",
"integrity": "sha512-/6ngYM7AapueqLtvOzjv9+11N2fHDSrkxeMF1YPE20WIfaaawiBg+HZH1E5lHrcJxlKR42t6XPOEmMmqcAsU1g==",
"requires": {
- "bindings": "1.2.1",
- "nan": "2.10.0"
+ "bindings": "~1.2.1",
+ "nan": "^2.0.7"
}
},
"deep-equal": {
@@ -125,8 +125,8 @@
"resolved": "https://registry.npmjs.org/didyoumean2/-/didyoumean2-1.3.0.tgz",
"integrity": "sha1-bjT0AUM1HJIGlulyO7oB/8C5ZAI=",
"requires": {
- "leven": "2.1.0",
- "lodash": "4.17.10"
+ "leven": "^2.0.0",
+ "lodash": "^4.17.2"
}
},
"escape-string-regexp": {
@@ -144,9 +144,9 @@
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
"integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
"requires": {
- "graceful-fs": "4.1.11",
- "jsonfile": "4.0.0",
- "universalify": "0.1.1"
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
}
},
"fs.realpath": {
@@ -159,12 +159,12 @@
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"requires": {
- "fs.realpath": "1.0.0",
- "inflight": "1.0.6",
- "inherits": "2.0.3",
- "minimatch": "3.0.4",
- "once": "1.4.0",
- "path-is-absolute": "1.0.1"
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
}
},
"graceful-fs": {
@@ -187,8 +187,8 @@
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
- "once": "1.4.0",
- "wrappy": "1.0.2"
+ "once": "^1.3.0",
+ "wrappy": "1"
}
},
"inherits": {
@@ -206,7 +206,7 @@
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
- "graceful-fs": "4.1.11"
+ "graceful-fs": "^4.1.6"
}
},
"leven": {
@@ -224,7 +224,7 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
- "brace-expansion": "1.1.11"
+ "brace-expansion": "^1.1.7"
}
},
"minimist": {
@@ -260,7 +260,7 @@
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
- "wrappy": "1.0.2"
+ "wrappy": "1"
}
},
"path-is-absolute": {
@@ -278,12 +278,12 @@
"resolved": "https://registry.npmjs.org/prompt/-/prompt-1.0.0.tgz",
"integrity": "sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4=",
"requires": {
- "colors": "1.2.5",
- "pkginfo": "0.4.1",
- "read": "1.0.7",
- "revalidator": "0.1.8",
- "utile": "0.3.0",
- "winston": "2.1.1"
+ "colors": "^1.1.2",
+ "pkginfo": "0.x.x",
+ "read": "1.0.x",
+ "revalidator": "0.1.x",
+ "utile": "0.3.x",
+ "winston": "2.1.x"
}
},
"read": {
@@ -291,7 +291,7 @@
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
"integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
"requires": {
- "mute-stream": "0.0.7"
+ "mute-stream": "~0.0.4"
}
},
"readdir-recursive": {
@@ -314,7 +314,7 @@
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
"requires": {
- "glob": "7.1.2"
+ "glob": "^7.0.5"
}
},
"stack-trace": {
@@ -327,7 +327,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
"requires": {
- "has-flag": "3.0.0"
+ "has-flag": "^3.0.0"
}
},
"universalify": {
@@ -340,12 +340,12 @@
"resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz",
"integrity": "sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo=",
"requires": {
- "async": "0.9.2",
- "deep-equal": "0.2.2",
- "i": "0.3.6",
- "mkdirp": "0.5.1",
- "ncp": "1.0.1",
- "rimraf": "2.6.2"
+ "async": "~0.9.0",
+ "deep-equal": "~0.2.1",
+ "i": "0.3.x",
+ "mkdirp": "0.x.x",
+ "ncp": "1.0.x",
+ "rimraf": "2.x.x"
}
},
"winston": {
@@ -353,13 +353,13 @@
"resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz",
"integrity": "sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4=",
"requires": {
- "async": "1.0.0",
- "colors": "1.0.3",
- "cycle": "1.0.3",
- "eyes": "0.1.8",
- "isstream": "0.1.2",
- "pkginfo": "0.3.1",
- "stack-trace": "0.0.10"
+ "async": "~1.0.0",
+ "colors": "1.0.x",
+ "cycle": "1.0.x",
+ "eyes": "0.1.x",
+ "isstream": "0.1.x",
+ "pkginfo": "0.3.x",
+ "stack-trace": "0.0.x"
},
"dependencies": {
"async": {
@@ -389,7 +389,7 @@
"resolved": "https://registry.npmjs.org/ws/-/ws-5.1.1.tgz",
"integrity": "sha512-bOusvpCb09TOBLbpMKszd45WKC2KPtxiyiHanv+H2DE3Az+1db5a/L7sVJZVDPUC1Br8f0SKRr1KjLpD1U/IAw==",
"requires": {
- "async-limiter": "1.0.0"
+ "async-limiter": "~1.0.0"
}
}
}
diff --git a/server/package.json b/server/package.json
index c9750f9..8094564 100644
--- a/server/package.json
+++ b/server/package.json
@@ -1,6 +1,6 @@
{
"name": "hack.chat-v2",
- "version": "2.0.1",
+ "version": "2.0.3",
"description": "a minimal distraction free chat application",
"main": "main.js",
"repository": {
diff --git a/server/src/commands/core/chat.js b/server/src/commands/core/chat.js
index 80241d5..168c0bb 100644
--- a/server/src/commands/core/chat.js
+++ b/server/src/commands/core/chat.js
@@ -48,6 +48,7 @@ exports.run = async (core, server, socket, data) => {
payload.trip = socket.trip;
}
+ // TODO: Add a more contained way for modules to interact, event hooks or something?
if(core.muzzledHashes && core.muzzledHashes[socket.hash]){
server.broadcast( payload, { channel: socket.channel, hash: socket.hash });
if(core.muzzledHashes[socket.hash].allies){
diff --git a/server/src/commands/core/disconnect.js b/server/src/commands/core/disconnect.js
deleted file mode 100644
index 9b54214..0000000
--- a/server/src/commands/core/disconnect.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- Description: This module will be directly called by the server event handler
- when a socket connection is closed or lost. It can calso be called
- by a client to have the connection severed.
-*/
-
-exports.run = async (core, server, socket, data) => {
- if (socket.channel) {
- server.broadcast({
- cmd: 'onlineRemove',
- nick: socket.nick
- }, { channel: socket.channel });
- }
-
- socket.terminate();
-};
-
-exports.info = {
- name: 'disconnect',
- description: 'Event handler or force disconnect (if your into that kind of thing)'
-}; \ No newline at end of file
diff --git a/server/src/commands/core/ping.js b/server/src/commands/core/ping.js
new file mode 100644
index 0000000..cf1d8a4
--- /dev/null
+++ b/server/src/commands/core/ping.js
@@ -0,0 +1,12 @@
+/*
+ Description: This module is only in place to supress error notices legacy sources may get
+*/
+
+exports.run = async (core, server, socket, data) => {
+ return;
+};
+
+exports.info = {
+ name: 'ping',
+ description: 'This module is only in place to supress error notices legacy sources may get'
+};
diff --git a/server/src/commands/internal/disconnect.js b/server/src/commands/internal/disconnect.js
new file mode 100644
index 0000000..bb3981b
--- /dev/null
+++ b/server/src/commands/internal/disconnect.js
@@ -0,0 +1,30 @@
+/*
+ Description: This module will be directly called by the server event handler
+ when a socket connection is closed or lost.
+*/
+
+exports.run = async (core, server, socket, data) => {
+ if (data.cmdKey !== server._cmdKey) {
+ // internal command attempt by client, increase rate limit chance and ignore
+ server._police.frisk(socket.remoteAddress, 20);
+
+ return;
+ }
+
+ if (socket.channel) {
+ server.broadcast({
+ cmd: 'onlineRemove',
+ nick: socket.nick
+ }, { channel: socket.channel });
+ }
+
+ socket.terminate();
+};
+
+exports.requiredData = ['cmdKey'];
+
+exports.info = {
+ name: 'disconnect',
+ usage: 'Internal Use Only',
+ description: 'Internally used to relay `onlineRemove` event to clients'
+};
diff --git a/server/src/commands/internal/socketreply.js b/server/src/commands/internal/socketreply.js
new file mode 100644
index 0000000..82834b7
--- /dev/null
+++ b/server/src/commands/internal/socketreply.js
@@ -0,0 +1,22 @@
+/*
+ Description: Used to relay warnings to clients internally
+*/
+
+exports.run = async (core, server, socket, data) => {
+ if (data.cmdKey !== server._cmdKey) {
+ // internal command attempt by client, increase rate limit chance and ignore
+ server._police.frisk(socket.remoteAddress, 20);
+
+ return;
+ }
+
+ server.reply({ cmd: 'warn', text: data.text }, socket);
+};
+
+exports.requiredData = ['cmdKey', 'text'];
+
+exports.info = {
+ name: 'socketreply',
+ usage: 'Internal Use Only',
+ description: 'Internally used to relay warnings to clients'
+};
diff --git a/server/src/commands/mod/dumb.js b/server/src/commands/mod/dumb.js
index ef2c5b2..0708fb8 100644
--- a/server/src/commands/mod/dumb.js
+++ b/server/src/commands/mod/dumb.js
@@ -1,4 +1,4 @@
-/*
+/*
* Description: Make a user (spammer) dumb
* Author: simple
*/
@@ -16,7 +16,7 @@ exports.run = async (core, server, socket, data) => {
if (typeof data.nick !== 'string') {
return;
}
-
+
let badClient = server.findSockets({ channel: socket.channel, nick: data.nick });
if (badClient.length === 0) {
@@ -38,20 +38,20 @@ exports.run = async (core, server, socket, data) => {
return;
}
-
+
let record = core.muzzledHashes[badClient.hash] = {
dumb:true
}
-
+
if(data.allies && Array.isArray(data.allies)){
record.allies = data.allies;
}
-
+
server.broadcast({
cmd: 'info',
text: `${socket.nick} muzzled ${data.nick} in ${socket.channel}, userhash: ${badClient.hash}`
}, { uType: 'mod' });
-
+
}
exports.requiredData = ['nick'];
@@ -59,5 +59,5 @@ exports.requiredData = ['nick'];
exports.info = {
name: 'dumb',
usage: 'dumb {nick} [allies...]',
- description: 'Cleanly disable a user messages and make him dumb'
+ description: 'Globally shadow mute a connection. Optional allies array will see muted messages.'
};
diff --git a/server/src/commands/mod/speak.js b/server/src/commands/mod/speak.js
index 422ad2c..643280b 100644
--- a/server/src/commands/mod/speak.js
+++ b/server/src/commands/mod/speak.js
@@ -1,9 +1,8 @@
-/*
+/*
* Description: Pardon a dumb user to be able to speak again
* Author: simple
*/
-
exports.run = async (core, server, socket, data) => {
if (socket.uType == 'user') {
// ignore if not mod or admin
@@ -18,7 +17,7 @@ exports.run = async (core, server, socket, data) => {
return;
}
-
+
let target;
if (typeof data.ip === 'string') {
@@ -26,14 +25,14 @@ exports.run = async (core, server, socket, data) => {
} else {
target = data.hash;
}
-
+
delete core.muzzledHashes[target];
-
+
server.broadcast({
cmd: 'info',
text: `${socket.nick} unmuzzled : ${target}`
}, { uType: 'mod' });
-
+
}
exports.info = {
diff --git a/server/src/core/server.js b/server/src/core/server.js
index 855aeba..ded7cac 100644
--- a/server/src/core/server.js
+++ b/server/src/core/server.js
@@ -11,6 +11,7 @@ const wsServer = require('ws').Server;
const socketReady = require('ws').OPEN;
const crypto = require('crypto');
const ipSalt = (Math.random().toString(36).substring(2, 16) + Math.random().toString(36).substring(2, (Math.random() * 16))).repeat(16);
+const internalCmdKey = (Math.random().toString(36).substring(2, 16) + Math.random().toString(36).substring(2, (Math.random() * 16))).repeat(16);
const Police = require('./rateLimiter');
const pulseSpeed = 16000; // ping all clients every X ms
@@ -26,6 +27,8 @@ class server extends wsServer {
this._core = core;
this._police = new Police();
this._cmdBlacklist = {};
+ this._cmdKey = internalCmdKey;
+
this._heartBeat = setInterval(((data) => {
this.beatHeart();
}).bind(this), pulseSpeed);
@@ -90,7 +93,11 @@ class server extends wsServer {
handleData (socket, data) {
// Don't penalize yet, but check whether IP is rate-limited
if (this._police.frisk(socket.remoteAddress, 0)) {
- this.reply({ cmd: 'warn', text: "Your IP is being rate-limited or blocked." }, socket);
+ this._core.commands.handleCommand(this, socket, {
+ cmd: 'socketreply',
+ cmdKey: this._cmdKey,
+ text: 'Your IP is being rate-limited or blocked.'
+ });
return;
}
@@ -116,7 +123,7 @@ class server extends wsServer {
return;
}
- if (typeof args.cmd === 'undefined' || args.cmd == 'ping') {
+ if (typeof args.cmd === 'undefined') {
return;
}
@@ -142,7 +149,10 @@ class server extends wsServer {
* @param {Object} socket Closing socket object
*/
handleClose (socket) {
- this._core.commands.handleCommand(this, socket, { cmd: 'disconnect' });
+ this._core.commands.handleCommand(this, socket, {
+ cmd: 'disconnect',
+ cmdKey: this._cmdKey
+ });
}
/**
diff --git a/server/src/managers/commands.js b/server/src/managers/commands.js
index c38fb4d..fd743fb 100644
--- a/server/src/managers/commands.js
+++ b/server/src/managers/commands.js
@@ -182,10 +182,11 @@ class CommandManager {
if (maybe) {
// Found a suggestion, pass it on to their dyslexic self
- return server.reply({
- cmd: 'warn',
+ return this.handleCommand(server, socket, {
+ cmd: 'socketreply',
+ cmdKey: server._cmdKey,
text: `Command not found, did you mean: \`${maybe}\`?`
- }, socket);
+ });
}
// Request so mangled that I don't even, silently fail
@@ -209,12 +210,12 @@ class CommandManager {
}
if (missing.length > 0) {
- let errText = `Failed to execute '${command.info.name}': missing required ${missing.join(', ')}\n\n`;
-
- server.reply({
- cmd: 'warn',
- text: errText
- }, socket);
+ console.log(`Failed to execute '${command.info.name}': missing required ${missing.join(', ')}\n\n`);
+ this.handleCommand(server, socket, {
+ cmd: 'socketreply',
+ cmdKey: server._cmdKey,
+ text: `Failed to execute '${command.info.name}': missing required ${missing.join(', ')}\n\n`
+ });
return null;
}
@@ -226,10 +227,11 @@ class CommandManager {
let errText = `Failed to execute '${command.info.name}': ${err}`;
console.log(errText);
- server.reply({
- cmd: 'warn',
+ this.handleCommand(server, socket, {
+ cmd: 'socketreply',
+ cmdKey: server._cmdKey,
text: errText
- }, socket);
+ });
return null;
}