ergo/irc/connection_limits/tor.go

56 lines
1.2 KiB
Go
Raw Normal View History

2019-02-26 03:50:43 +01:00
// Copyright (c) 2019 Shivaram Lingamneni <slingamn@cs.stanford.edu>
// released under the MIT license
package connection_limits
import (
"errors"
"sync"
"time"
)
var (
ErrLimitExceeded = errors.New("too many concurrent connections")
ErrThrottleExceeded = errors.New("too many recent connection attempts")
)
// TorLimiter is a combined limiter and throttler for use on connections
// proxied from a Tor hidden service (so we don't have meaningful IPs,
// a notion of CIDR width, etc.)
type TorLimiter struct {
sync.Mutex
numConnections int
maxConnections int
throttle GenericThrottle
}
func (tl *TorLimiter) Configure(maxConnections int, duration time.Duration, maxConnectionsPerDuration int) {
tl.Lock()
defer tl.Unlock()
tl.maxConnections = maxConnections
tl.throttle.Duration = duration
tl.throttle.Limit = maxConnectionsPerDuration
}
func (tl *TorLimiter) AddClient() error {
tl.Lock()
defer tl.Unlock()
if tl.maxConnections != 0 && tl.maxConnections <= tl.numConnections {
return ErrLimitExceeded
}
throttled, _ := tl.throttle.Touch()
if throttled {
return ErrThrottleExceeded
}
tl.numConnections += 1
return nil
}
func (tl *TorLimiter) RemoveClient() {
tl.Lock()
tl.numConnections -= 1
tl.Unlock()
}