mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-23 04:19:25 +01:00
56 lines
1.2 KiB
Go
56 lines
1.2 KiB
Go
// 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()
|
|
}
|