• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RateLimitManager()58   RateLimitManager() { };
~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:
RateLimit(int max,int per_x_secs)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 
~RateLimit()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
IsWithinRateLimit()94     bool IsWithinRateLimit() {
95       return (talk_base::TimeSince(NextTimeAllowedForCounter()) >= 0);
96     }
97 
98     // Updates time and counter for rate limit
UpdateRateLimit()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
PreviousTimeAtCounter()107     uint32 PreviousTimeAtCounter() {
108       return event_times_[counter_];
109     }
110 
111     // The time that the next event is allowed to occur
NextTimeAllowedForCounter()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