aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/serverLib/RateLimiter.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/serverLib/RateLimiter.js')
-rw-r--r--server/src/serverLib/RateLimiter.js105
1 files changed, 74 insertions, 31 deletions
diff --git a/server/src/serverLib/RateLimiter.js b/server/src/serverLib/RateLimiter.js
index 43cf077..3f9bc27 100644
--- a/server/src/serverLib/RateLimiter.js
+++ b/server/src/serverLib/RateLimiter.js
@@ -1,39 +1,60 @@
+import { RateLimits } from '../utility/Constants';
+
/**
* Tracks frequency of occurances based on `id` (remote address), then allows or
* denies command execution based on comparison with `threshold`
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
+ * @property {Object} data - The current stats data
+ * @author Marzavec ( https://github.com/marzavec )
+ * @author Andrew Belt ( https://github.com/AndrewBelt )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
-
class RateLimiter {
/**
- * Create a ratelimiter instance.
- */
- constructor () {
+ * Create a ratelimiter instance
+ */
+ constructor() {
+ /**
+ * Data holder rate limit records
+ * @type {Object}
+ */
this.records = {};
- this.halflife = 30 * 1000; // milliseconds
- this.threshold = 25;
+
+ /**
+ * Time in milliseconds to decrement ratelimit weight
+ * @type {Number}
+ */
+ this.halflife = RateLimits.halflife;
+
+ /**
+ * Weight until ratelimited
+ * @type {Number}
+ */
+ this.threshold = RateLimits.threshold;
+
+ /**
+ * Stores the associated connection fingerprint with record id
+ * @type {Array}
+ */
this.hashes = [];
}
/**
* Finds current score by `id`
- *
* @param {String} id target id / address
- *
+ * @private
* @return {Object} Object containing the record meta
*/
- search (id) {
+ search(id) {
let record = this.records[id];
if (!record) {
- record = this.records[id] = {
+ this.records[id] = {
time: Date.now(),
- score: 0
- }
+ score: 0,
+ };
+
+ record = this.records[id];
}
return record;
@@ -41,20 +62,22 @@ class RateLimiter {
/**
* Adjusts the current ratelimit score by `deltaScore`
- *
* @param {String} id target id / address
* @param {Number} deltaScore amount to adjust current score by
- *
+ * @example
+ * // Penalize by 1 and store if connection is ratelimited or not
+ * let isLimited = police.frisk(socket.address, 1);
+ * @public
* @return {Boolean} True if record threshold has been exceeded
*/
- frisk (id, deltaScore) {
- let record = this.search(id);
+ frisk(id, deltaScore) {
+ const record = this.search(id);
if (record.arrested) {
return true;
}
- record.score *= Math.pow(2, -(Date.now() - record.time ) / this.halflife);
+ record.score *= 2 ** -(Date.now() - record.time) / this.halflife;
record.score += deltaScore;
record.time = Date.now();
@@ -67,11 +90,16 @@ class RateLimiter {
/**
* Statically set server to no longer accept traffic from `id`
- *
* @param {String} id target id / address
+ * @example
+ * // Usage within a command module:
+ * let badClient = server.findSockets({ channel: socket.channel, nick: targetNick });
+ * server.police.arrest(badClient[0].address, badClient[0].hash);
+ * @public
+ * @return {void}
*/
- arrest (id, hash) {
- let record = this.search(id);
+ arrest(id, hash) {
+ const record = this.search(id);
record.arrested = true;
this.hashes[hash] = id;
@@ -79,17 +107,32 @@ class RateLimiter {
/**
* Remove statically assigned limit from `id`
- *
* @param {String} id target id / address
+ * @example
+ * // Usage within a command module:
+ * server.police.pardon('targetHashOrIP');
+ * @public
+ * @return {void}
*/
- pardon (id) {
- if (typeof this.hashes[id] !== 'undefined') {
- id = this.hashes[id];
+ pardon(id) {
+ let targetId = id;
+ if (typeof this.hashes[targetId] !== 'undefined') {
+ targetId = this.hashes[targetId];
}
- let record = this.search(id);
+ const record = this.search(targetId);
record.arrested = false;
}
+
+ /**
+ * Clear all records
+ * @public
+ * @return {void}
+ */
+ clear() {
+ this.records = {};
+ this.hashes = [];
+ }
}
-module.exports = RateLimiter;
+export default RateLimiter;