Removed exported methods from ratelimiter package
This commit is contained in:
parent
5f0a91a127
commit
8bdadaae59
|
@ -2,8 +2,7 @@ package ratelimiter
|
||||||
|
|
||||||
/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
|
/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
|
||||||
|
|
||||||
/* This file contains a port of the ratelimited from the linux kernel version
|
/* This file contains a port of the rate-limiter from the linux kernel version */
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
@ -12,11 +11,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RatelimiterPacketsPerSecond = 20
|
packetsPerSecond = 20
|
||||||
RatelimiterPacketsBurstable = 5
|
packetsBurstable = 5
|
||||||
RatelimiterGarbageCollectTime = time.Second
|
garbageCollectTime = time.Second
|
||||||
RatelimiterPacketCost = 1000000000 / RatelimiterPacketsPerSecond
|
packetCost = 1000000000 / packetsPerSecond
|
||||||
RatelimiterMaxTokens = RatelimiterPacketCost * RatelimiterPacketsBurstable
|
maxTokens = packetCost * packetsBurstable
|
||||||
)
|
)
|
||||||
|
|
||||||
type RatelimiterEntry struct {
|
type RatelimiterEntry struct {
|
||||||
|
@ -45,6 +44,8 @@ func (rate *Ratelimiter) Init() {
|
||||||
rate.mutex.Lock()
|
rate.mutex.Lock()
|
||||||
defer rate.mutex.Unlock()
|
defer rate.mutex.Unlock()
|
||||||
|
|
||||||
|
// stop any ongoing garbage collection routine
|
||||||
|
|
||||||
if rate.stop != nil {
|
if rate.stop != nil {
|
||||||
close(rate.stop)
|
close(rate.stop)
|
||||||
}
|
}
|
||||||
|
@ -53,6 +54,8 @@ func (rate *Ratelimiter) Init() {
|
||||||
rate.tableIPv4 = make(map[[net.IPv4len]byte]*RatelimiterEntry)
|
rate.tableIPv4 = make(map[[net.IPv4len]byte]*RatelimiterEntry)
|
||||||
rate.tableIPv6 = make(map[[net.IPv6len]byte]*RatelimiterEntry)
|
rate.tableIPv6 = make(map[[net.IPv6len]byte]*RatelimiterEntry)
|
||||||
|
|
||||||
|
// start garbage collection routine
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
timer := time.NewTimer(time.Second)
|
timer := time.NewTimer(time.Second)
|
||||||
for {
|
for {
|
||||||
|
@ -60,39 +63,32 @@ func (rate *Ratelimiter) Init() {
|
||||||
case <-rate.stop:
|
case <-rate.stop:
|
||||||
return
|
return
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
rate.garbageCollectEntries()
|
func() {
|
||||||
|
rate.mutex.Lock()
|
||||||
|
defer rate.mutex.Unlock()
|
||||||
|
|
||||||
|
for key, entry := range rate.tableIPv4 {
|
||||||
|
entry.mutex.Lock()
|
||||||
|
if time.Now().Sub(entry.lastTime) > garbageCollectTime {
|
||||||
|
delete(rate.tableIPv4, key)
|
||||||
|
}
|
||||||
|
entry.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, entry := range rate.tableIPv6 {
|
||||||
|
entry.mutex.Lock()
|
||||||
|
if time.Now().Sub(entry.lastTime) > garbageCollectTime {
|
||||||
|
delete(rate.tableIPv6, key)
|
||||||
|
}
|
||||||
|
entry.mutex.Unlock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
timer.Reset(time.Second)
|
timer.Reset(time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rate *Ratelimiter) garbageCollectEntries() {
|
|
||||||
rate.mutex.Lock()
|
|
||||||
|
|
||||||
// remove unused IPv4 entries
|
|
||||||
|
|
||||||
for key, entry := range rate.tableIPv4 {
|
|
||||||
entry.mutex.Lock()
|
|
||||||
if time.Now().Sub(entry.lastTime) > RatelimiterGarbageCollectTime {
|
|
||||||
delete(rate.tableIPv4, key)
|
|
||||||
}
|
|
||||||
entry.mutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove unused IPv6 entries
|
|
||||||
|
|
||||||
for key, entry := range rate.tableIPv6 {
|
|
||||||
entry.mutex.Lock()
|
|
||||||
if time.Now().Sub(entry.lastTime) > RatelimiterGarbageCollectTime {
|
|
||||||
delete(rate.tableIPv6, key)
|
|
||||||
}
|
|
||||||
entry.mutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
rate.mutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rate *Ratelimiter) Allow(ip net.IP) bool {
|
func (rate *Ratelimiter) Allow(ip net.IP) bool {
|
||||||
var entry *RatelimiterEntry
|
var entry *RatelimiterEntry
|
||||||
var KeyIPv4 [net.IPv4len]byte
|
var KeyIPv4 [net.IPv4len]byte
|
||||||
|
@ -120,7 +116,7 @@ func (rate *Ratelimiter) Allow(ip net.IP) bool {
|
||||||
if entry == nil {
|
if entry == nil {
|
||||||
rate.mutex.Lock()
|
rate.mutex.Lock()
|
||||||
entry = new(RatelimiterEntry)
|
entry = new(RatelimiterEntry)
|
||||||
entry.tokens = RatelimiterMaxTokens - RatelimiterPacketCost
|
entry.tokens = maxTokens - packetCost
|
||||||
entry.lastTime = time.Now()
|
entry.lastTime = time.Now()
|
||||||
if IPv4 != nil {
|
if IPv4 != nil {
|
||||||
rate.tableIPv4[KeyIPv4] = entry
|
rate.tableIPv4[KeyIPv4] = entry
|
||||||
|
@ -137,14 +133,14 @@ func (rate *Ratelimiter) Allow(ip net.IP) bool {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
entry.tokens += now.Sub(entry.lastTime).Nanoseconds()
|
entry.tokens += now.Sub(entry.lastTime).Nanoseconds()
|
||||||
entry.lastTime = now
|
entry.lastTime = now
|
||||||
if entry.tokens > RatelimiterMaxTokens {
|
if entry.tokens > maxTokens {
|
||||||
entry.tokens = RatelimiterMaxTokens
|
entry.tokens = maxTokens
|
||||||
}
|
}
|
||||||
|
|
||||||
// subtract cost of packet
|
// subtract cost of packet
|
||||||
|
|
||||||
if entry.tokens > RatelimiterPacketCost {
|
if entry.tokens > packetCost {
|
||||||
entry.tokens -= RatelimiterPacketCost
|
entry.tokens -= packetCost
|
||||||
entry.mutex.Unlock()
|
entry.mutex.Unlock()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestRatelimiter(t *testing.T) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < RatelimiterPacketsBurstable; i++ {
|
for i := 0; i < packetsBurstable; i++ {
|
||||||
Add(RatelimiterResult{
|
Add(RatelimiterResult{
|
||||||
allowed: true,
|
allowed: true,
|
||||||
text: "inital burst",
|
text: "inital burst",
|
||||||
|
@ -42,7 +42,7 @@ func TestRatelimiter(t *testing.T) {
|
||||||
|
|
||||||
Add(RatelimiterResult{
|
Add(RatelimiterResult{
|
||||||
allowed: true,
|
allowed: true,
|
||||||
wait: Nano(time.Second.Nanoseconds() / RatelimiterPacketsPerSecond),
|
wait: Nano(time.Second.Nanoseconds() / packetsPerSecond),
|
||||||
text: "filling tokens for single packet",
|
text: "filling tokens for single packet",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ func TestRatelimiter(t *testing.T) {
|
||||||
|
|
||||||
Add(RatelimiterResult{
|
Add(RatelimiterResult{
|
||||||
allowed: true,
|
allowed: true,
|
||||||
wait: 2 * Nano(time.Second.Nanoseconds()/RatelimiterPacketsPerSecond),
|
wait: 2 * (Nano(time.Second.Nanoseconds() / packetsPerSecond)),
|
||||||
text: "filling tokens for two packet burst",
|
text: "filling tokens for two packet burst",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue