Bug 428548: Restrict the total number of safebrowsing update requests per hour. r=tony, a=mconnor

This commit is contained in:
dcamp@mozilla.com 2008-04-16 14:21:13 -07:00
parent 88fbcb156f
commit 1910735610
2 changed files with 31 additions and 66 deletions

View File

@ -98,6 +98,8 @@ function PROT_ListManager() {
this.requestBackoff_ = new RequestBackoff(3 /* num errors */,
10*60*1000 /* error time, 10min */,
4 /* num requests */,
60*60*1000 /* request time, 60 min */,
60*60*1000 /* backoff interval, 60min */,
6*60*60*1000 /* max backoff, 6hr */);
@ -450,6 +452,8 @@ PROT_ListManager.prototype.makeUpdateRequest_ = function(tableData) {
return;
}
this.requestBackoff_.noteRequest();
if (!streamer.downloadUpdates(tableList,
request,
this.keyManager_.getClientKey(),

View File

@ -52,16 +52,26 @@ const HTTP_TEMPORARY_REDIRECT = 307;
* @param maxErrors Number the number of errors needed to trigger backoff
* @param errorPeriod Number time (ms) in which maxErros have to occur to
* trigger the backoff behavior
* @param maxRequests Number the number of requests needed to trigger backoff
* @param requestPeriod Number time (ms) in which maxRequests have to occur to
* trigger the backoff behavior
* @param timeoutIncrement Number time (ms) the starting timeout period
* we double this time for consecutive errors
* @param maxTimeout Number time (ms) maximum timeout period
*/
function RequestBackoff(maxErrors, errorPeriod, timeoutIncrement, maxTimeout) {
function RequestBackoff(maxErrors, errorPeriod,
maxRequests, requestPeriod,
timeoutIncrement, maxTimeout) {
this.MAX_ERRORS_ = maxErrors;
this.ERROR_PERIOD_ = errorPeriod;
this.MAX_REQUESTS_ = maxRequests;
this.REQUEST_PERIOD_ = requestPeriod;
this.TIMEOUT_INCREMENT_ = timeoutIncrement;
this.MAX_TIMEOUT_ = maxTimeout;
// Queue of ints keeping the time of all requests
this.requestTimes_ = [];
// Queue of ints keeping the time of errors.
this.errorTimes_ = [];
this.errorTimeout_ = 0;
@ -83,7 +93,22 @@ RequestBackoff.prototype.reset = function() {
* Check to see if we can make a request.
*/
RequestBackoff.prototype.canMakeRequest = function() {
return Date.now() > this.nextRequestTime_;
var now = Date.now();
if (now <= this.nextRequestTime_) {
return false;
}
return (this.requestTimes_.length < this.MAX_REQUESTS_ ||
(now - this.requestTimes_[0]) > this.REQUEST_PERIOD_);
}
RequestBackoff.prototype.noteRequest = function() {
var now = Date.now();
this.requestTimes_.push(now);
// We only care about keeping track of MAX_REQUESTS
if (this.requestTimes_.length > this.MAX_REQUESTS_)
this.requestTimes_.shift();
}
/**
@ -131,67 +156,3 @@ RequestBackoff.prototype.isErrorStatus = function(status) {
HTTP_TEMPORARY_REDIRECT == status);
}
#ifdef 0
// Some unittests (e.g., paste into JS shell)
var jslib = Cc["@mozilla.org/url-classifier/jslib;1"].
getService().wrappedJSObject;
var _Datenow = jslib.Date.now;
function setNow(time) {
jslib.Date.now = function() {
return time;
}
}
// 2 errors, 5ms time period, 5ms backoff interval, 20ms max delay
var rb = new jslib.RequestBackoff(2, 5, 5, 20);
setNow(1);
rb.noteServerResponse(200)
if (!rb.canMakeRequest()) throw "expected ok";
setNow(2);
rb.noteServerResponse(500);
if (!rb.canMakeRequest()) throw "expected ok";
setNow(3);
rb.noteServerResponse(200)
if (!rb.canMakeRequest()) throw "expected ok";
// Trigger backoff
setNow(4);
rb.noteServerResponse(502)
if (rb.canMakeRequest()) throw "expected failed";
if (rb.nextRequestTime_ != 9) throw "wrong next request time";
// Trigger backoff again
setNow(10);
if (!rb.canMakeRequest()) throw "expected ok";
rb.noteServerResponse(503)
if (rb.canMakeRequest()) throw "expected failed";
if (rb.nextRequestTime_ != 25) throw "wrong next request time";
// Trigger backoff a third time and hit max timeout
setNow(30);
if (!rb.canMakeRequest()) throw "expected ok";
rb.noteServerResponse(302)
if (rb.canMakeRequest()) throw "expected failed";
if (rb.nextRequestTime_ != 50) throw "wrong next request time";
// Request goes through
setNow(100);
if (!rb.canMakeRequest()) throw "expected ok";
rb.noteServerResponse(200)
if (!rb.canMakeRequest()) throw "expected ok";
if (rb.nextRequestTime_ != 0) throw "wrong next request time";
// Another error (shouldn't trigger backoff)
setNow(101);
rb.noteServerResponse(500);
if (!rb.canMakeRequest()) throw "expected ok";
// Another error, but not in ERROR_PERIOD, so it should be ok
setNow(107);
rb.noteServerResponse(500);
if (!rb.canMakeRequest()) throw "expected ok";
jslib.Date.now = _Datenow;
#endif