Stun Server  Compliant with the latest RFCs including 5389, 5769, and 5780
discover the local host's own external IP address
ratelimiter.cpp
Go to the documentation of this file.
1 #include "commonincludes.hpp"
2 #include "socketaddress.h"
3 #include "fasthash.h"
4 #include "ratelimiter.h"
5 
6 
7 RateLimiter::RateLimiter(size_t tablesize, bool isUsingLock)
8 {
9  _table.InitTable(tablesize, tablesize/2);
10  this->_isUsingLock = isUsingLock;
11  pthread_mutex_init(&_mutex, NULL);
12 }
13 
15 {
16  pthread_mutex_destroy(&_mutex);
17 }
18 
19 
21 {
22  return time(NULL);
23 }
24 
25 uint64_t RateLimiter::get_rate(const RateTracker* pRT)
26 {
28  {
29  return 0;
30  }
31 
32  time_t seconds = 1;
33 
34  if (pRT->lastEntryTime > pRT->firstEntryTime)
35  {
36  seconds = pRT->lastEntryTime - pRT->firstEntryTime;
37  }
38 
39  uint64_t rate = (pRT->count * 3600) / seconds;
40 
41  return rate;
42 }
43 
45 {
46  if (_isUsingLock)
47  {
48  pthread_mutex_lock(&_mutex);
49  }
50 
51  bool result = RateCheckImpl(addr);
52 
53  if (_isUsingLock)
54  {
55  pthread_mutex_unlock(&_mutex);
56  }
57 
58  return result;
59 
60 }
61 
63 {
64  RateTrackerAddress rtaddr;
65  addr.GetIP(rtaddr.addrbytes, sizeof(rtaddr.addrbytes));
66  time_t currentTime = get_time();
67 
68  RateTracker* pRT = this->_table.Lookup(rtaddr);
69  uint64_t rate = 0;
70 
71 
72  // handle these cases differently:
73  // 1. Not in the table
74  // Insert into table
75  // if table is full, reset the table and re-insert
76  // return true
77  // 2. In the penalty box
78  // Check for parole eligibility
79  // otherwise, return false
80  // 3. Not in the penalty box.
81  // Remove from table if his previous record is sufficiently old (and return true)
82  //
83 
84 
85  if (pRT == NULL)
86  {
87  RateTracker rt;
88  rt.count = 1;
89  rt.firstEntryTime = currentTime;
91  rt.penaltyTime = 0;
92 
93  int result = _table.Insert(rtaddr, rt);
94 
95  if (result == -1)
96  {
97  // the table is full - try again after dumping the table
98  // I've considered a half dozen alternatives to doing this, but this is the simplest
99  _table.Reset();
100  _table.Insert(rtaddr, rt);
101  }
102  return true;
103  }
104 
105 
106  pRT->count++;
107  pRT->lastEntryTime = currentTime;
108  rate = get_rate(pRT);
109 
110 
111  if (pRT->penaltyTime != 0)
112  {
113  if (pRT->penaltyTime >= currentTime)
114  {
115  return false;
116  }
117 
118  if (rate < MAX_RATE)
119  {
120  pRT->penaltyTime = 0;
121  // not reseting firstEntryTime or lastEntryTime.
122  return true;
123  }
124 
125  // he's out of penalty, but is still flooding us. Tack on another hour
126  pRT->penaltyTime = currentTime + PENALTY_TIME_SECONDS;
127  return false;
128  }
129 
130  if (rate >= MAX_RATE)
131  {
132  pRT->penaltyTime = currentTime + PENALTY_TIME_SECONDS; // welcome to the penalty box
133  return false;
134  }
135 
137  {
138  // he's been a good citizen this whole time, we can take him out of the table
139  // to save room for another entry
140  _table.Remove(rtaddr);
141  }
142 
143  return true;
144 }
145 
FastHashDynamic< RateTrackerAddress, RateTracker > _table
Definition: ratelimiter.h:48
bool _isUsingLock
Definition: ratelimiter.h:50
void Reset()
Definition: fasthash.h:239
bool RateCheckImpl(const CSocketAddress &addr)
Definition: ratelimiter.cpp:62
uint64_t get_rate(const RateTracker *pRT)
Definition: ratelimiter.cpp:25
static const uint64_t MIN_COUNT_FOR_CONSIDERATION
Definition: ratelimiter.h:59
uint64_t addrbytes[2]
Definition: ratelimiter.h:17
time_t penaltyTime
Definition: ratelimiter.h:12
int Insert(const K &key, V &value)
Definition: fasthash.h:284
virtual ~RateLimiter()
Definition: ratelimiter.cpp:14
static const time_t RESET_INTERVAL_SECONDS
Definition: ratelimiter.h:60
uint64_t count
Definition: ratelimiter.h:9
V * Lookup(const K &key)
Definition: fasthash.h:351
size_t GetIP(void *pAddr, size_t length) const
pthread_mutex_t _mutex
Definition: ratelimiter.h:52
static const time_t PENALTY_TIME_SECONDS
Definition: ratelimiter.h:61
static const uint64_t MAX_RATE
Definition: ratelimiter.h:58
int InitTable(size_t fsize, size_t tsize)
Definition: fasthash.h:471
int Remove(const K &key)
Definition: fasthash.h:316
time_t firstEntryTime
Definition: ratelimiter.h:10
RateLimiter(size_t tablesize, bool isUsingLock)
Definition: ratelimiter.cpp:7
virtual time_t get_time()
Definition: ratelimiter.cpp:20
time_t lastEntryTime
Definition: ratelimiter.h:11
bool RateCheck(const CSocketAddress &addr)
Definition: ratelimiter.cpp:44