Limit requestPlaylist to once per 60 seconds

If clients call it quickly in succession with large playlists, it can
cause node to get stuck stringifying socket.io frames and cause an out
of memory crash.
This commit is contained in:
calzoneman 2016-02-06 19:40:50 -08:00
parent 65d4ea9496
commit b3c85e8534
4 changed files with 46 additions and 7 deletions

View file

@ -2,7 +2,7 @@
"author": "Calvin Montgomery",
"name": "CyTube",
"description": "Online media synchronizer and chat",
"version": "3.14.2",
"version": "3.14.3",
"repository": {
"url": "http://github.com/calzoneman/sync"
},

View file

@ -11,6 +11,13 @@ var CustomEmbedFilter = require("../customembed").filter;
var XSS = require("../xss");
const MAX_ITEMS = Config.get("playlist.max-items");
// Limit requestPlaylist to once per 60 seconds
const REQ_PLAYLIST_THROTTLE = {
burst: 1,
sustained: 0,
cooldown: 60
};
const TYPE_QUEUE = {
id: "string,boolean",
@ -216,9 +223,7 @@ PlaylistModule.prototype.onUserPostJoin = function (user) {
user.socket.on("playerReady", function () {
self.sendChangeMedia([user]);
});
user.socket.on("requestPlaylist", function () {
self.sendPlaylist([user]);
});
user.socket.on("requestPlaylist", this.handleRequestPlaylist.bind(this, user));
user.on("login", function () {
self.sendPlaylist([user]);
});
@ -1323,4 +1328,16 @@ PlaylistModule.prototype.handleQueuePlaylist = function (user, data) {
});
};
PlaylistModule.prototype.handleRequestPlaylist = function (user) {
if (user.reqPlaylistLimiter.throttle(REQ_PLAYLIST_THROTTLE)) {
user.socket.emit("errorMsg", {
msg: "Get Playlist URLs is limited to 1 usage every 60 seconds. " +
"Please try again later.",
code: "REQ_PLAYLIST_LIMIT_REACHED"
});
} else {
this.sendPlaylist([user]);
}
};
module.exports = PlaylistModule;

View file

@ -21,6 +21,7 @@ function User(socket) {
self.channel = null;
self.queueLimiter = util.newRateLimiter();
self.chatLimiter = util.newRateLimiter();
self.reqPlaylistLimiter = util.newRateLimiter();
self.awaytimer = false;
var announcement = Server.getServer().announcement;

View file

@ -490,9 +490,14 @@ $("#voteskip").click(function() {
$("#getplaylist").click(function() {
var callback = function(data) {
hidePlayer();
socket.listeners("playlist").splice(
socket.listeners("playlist").indexOf(callback)
);
var idx = socket.listeners("errorMsg").indexOf(errCallback);
if (idx >= 0) {
socket.listeners("errorMsg").splice(idx);
}
idx = socket.listeners("playlist").indexOf(callback);
if (idx >= 0) {
socket.listeners("playlist").splice(idx);
}
var list = [];
for(var i = 0; i < data.length; i++) {
var entry = formatURL(data[i].media);
@ -524,6 +529,22 @@ $("#getplaylist").click(function() {
outer.modal();
};
socket.on("playlist", callback);
var errCallback = function(data) {
if (data.code !== "REQ_PLAYLIST_LIMIT_REACHED") {
return;
}
var idx = socket.listeners("errorMsg").indexOf(errCallback);
if (idx >= 0) {
socket.listeners("errorMsg").splice(idx);
}
idx = socket.listeners("playlist").indexOf(callback);
if (idx >= 0) {
socket.listeners("playlist").splice(idx);
}
};
socket.on("errorMsg", errCallback);
socket.emit("requestPlaylist");
});