Removed exported methods from ratelimiter package

This commit is contained in:
Mathias Hall-Andersen 2018-02-11 23:01:55 +01:00
parent 5f0a91a127
commit 8bdadaae59
2 changed files with 38 additions and 42 deletions

View file

@ -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
} }

View file

@ -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",
}) })