1 /* 2 * libjingle 3 * Copyright 2004--2006, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef _RATELIMITMANAGER_H_ 29 #define _RATELIMITMANAGER_H_ 30 31 #include "talk/base/time.h" 32 #include "talk/base/taskrunner.h" 33 #include <map> 34 35 namespace buzz { 36 37 ///////////////////////////////////////////////////////////////////// 38 // 39 // RATELIMITMANAGER 40 // 41 ///////////////////////////////////////////////////////////////////// 42 // 43 // RateLimitManager imposes client-side rate limiting for xmpp tasks and 44 // other events. It ensures that no more than i events with a given name 45 // can occur within k seconds. 46 // 47 // A buffer tracks the previous max_count events. Before an event is allowed 48 // to occur, it can check its rate limit with a call to VerifyRateLimit. 49 // VerifyRateLimit will look up the i-th to last event and if more than 50 // k seconds have passed since then, it will return true and update the 51 // appropriate rate limits. Else, it will return false. 52 // 53 ///////////////////////////////////////////////////////////////////// 54 55 class RateLimitManager { 56 public: 57 58 RateLimitManager() { }; 59 ~RateLimitManager() { 60 for (RateLimitMap::iterator it = rate_limits_.begin(); 61 it != rate_limits_.end(); ++it) { 62 delete it->second; 63 } 64 }; 65 66 // Checks if the event is under the defined rate limit and updates the 67 // rate limit if so. Returns true if it's under the rate limit. 68 bool VerifyRateLimit(const std::string event_name, int max_count, 69 int per_x_seconds); 70 71 // Checks if the event is under the defined rate limit and updates the 72 // rate limit if so *or* if always_update = true. 73 bool VerifyRateLimit(const std::string event_name, int max_count, 74 int per_x_seconds, bool always_update); 75 76 private: 77 class RateLimit { 78 public: 79 RateLimit(int max, int per_x_secs) : counter_(0), max_count_(max), 80 per_x_seconds_(per_x_secs) { 81 event_times_ = new uint32[max_count_]; 82 for (int i = 0; i < max_count_; i++) { 83 event_times_[i] = 0; 84 } 85 } 86 87 ~RateLimit() { 88 if (event_times_) { 89 delete[] event_times_; 90 } 91 } 92 93 // True iff the current time >= to the next song allowed time 94 bool IsWithinRateLimit() { 95 return (talk_base::TimeSince(NextTimeAllowedForCounter()) >= 0); 96 } 97 98 // Updates time and counter for rate limit 99 void UpdateRateLimit() { 100 event_times_[counter_] = talk_base::Time(); 101 counter_ = (counter_ + 1) % max_count_; 102 } 103 104 private: 105 106 // The time at which the i-th (where i = max_count) event occured 107 uint32 PreviousTimeAtCounter() { 108 return event_times_[counter_]; 109 } 110 111 // The time that the next event is allowed to occur 112 uint32 NextTimeAllowedForCounter() { 113 return PreviousTimeAtCounter() + per_x_seconds_ * talk_base::kSecToMsec; 114 } 115 116 int counter_; // count modulo max_count of the current event 117 int max_count_; // max number of events that can occur within per_x_seconds 118 int per_x_seconds_; // interval size for rate limit 119 uint32* event_times_; // buffer of previous max_count event 120 }; 121 122 typedef std::map<const std::string, RateLimit*> RateLimitMap; 123 124 // Maps from event name to its rate limit 125 RateLimitMap rate_limits_; 126 127 // Returns rate limit for event with specified name 128 RateLimit* GetRateLimit(const std::string event_name); 129 130 // True iff the current time >= to the next song allowed time 131 bool IsWithinRateLimit(const std::string event_name); 132 133 // Updates time and counter for rate limit 134 void UpdateRateLimit(const std::string event_name, int max_count, 135 int per_x_seconds); 136 137 }; 138 139 } 140 141 #endif //_RATELIMITMANAGER_H_ 142