blob: 288084f11eb6c85a8c77eb2f08ba0270c20c207c [file] [log] [blame]
/*
* libjingle
* Copyright 2004--2006, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _RATELIMITMANAGER_H_
#define _RATELIMITMANAGER_H_
#include "talk/base/timeutils.h"
#include "talk/base/taskrunner.h"
#include <map>
namespace buzz {
/////////////////////////////////////////////////////////////////////
//
// RATELIMITMANAGER
//
/////////////////////////////////////////////////////////////////////
//
// RateLimitManager imposes client-side rate limiting for xmpp tasks and
// other events. It ensures that no more than i events with a given name
// can occur within k seconds.
//
// A buffer tracks the previous max_count events. Before an event is allowed
// to occur, it can check its rate limit with a call to VerifyRateLimit.
// VerifyRateLimit will look up the i-th to last event and if more than
// k seconds have passed since then, it will return true and update the
// appropriate rate limits. Else, it will return false.
//
/////////////////////////////////////////////////////////////////////
class RateLimitManager {
public:
RateLimitManager() { };
~RateLimitManager() {
for (RateLimitMap::iterator it = rate_limits_.begin();
it != rate_limits_.end(); ++it) {
delete it->second;
}
};
// Checks if the event is under the defined rate limit and updates the
// rate limit if so. Returns true if it's under the rate limit.
bool VerifyRateLimit(const std::string event_name, int max_count,
int per_x_seconds);
// Checks if the event is under the defined rate limit and updates the
// rate limit if so *or* if always_update = true.
bool VerifyRateLimit(const std::string event_name, int max_count,
int per_x_seconds, bool always_update);
private:
class RateLimit {
public:
RateLimit(int max, int per_x_secs) : counter_(0), max_count_(max),
per_x_seconds_(per_x_secs) {
event_times_ = new uint32[max_count_];
for (int i = 0; i < max_count_; i++) {
event_times_[i] = 0;
}
}
~RateLimit() {
if (event_times_) {
delete[] event_times_;
}
}
// True iff the current time >= to the next song allowed time
bool IsWithinRateLimit() {
return (talk_base::TimeSince(NextTimeAllowedForCounter()) >= 0);
}
// Updates time and counter for rate limit
void UpdateRateLimit() {
event_times_[counter_] = talk_base::Time();
counter_ = (counter_ + 1) % max_count_;
}
private:
// The time at which the i-th (where i = max_count) event occured
uint32 PreviousTimeAtCounter() {
return event_times_[counter_];
}
// The time that the next event is allowed to occur
uint32 NextTimeAllowedForCounter() {
return PreviousTimeAtCounter() + per_x_seconds_ * talk_base::kSecToMsec;
}
int counter_; // count modulo max_count of the current event
int max_count_; // max number of events that can occur within per_x_seconds
int per_x_seconds_; // interval size for rate limit
uint32* event_times_; // buffer of previous max_count event
};
typedef std::map<const std::string, RateLimit*> RateLimitMap;
// Maps from event name to its rate limit
RateLimitMap rate_limits_;
// Returns rate limit for event with specified name
RateLimit* GetRateLimit(const std::string event_name);
// True iff the current time >= to the next song allowed time
bool IsWithinRateLimit(const std::string event_name);
// Updates time and counter for rate limit
void UpdateRateLimit(const std::string event_name, int max_count,
int per_x_seconds);
};
}
#endif //_RATELIMITMANAGER_H_