mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-06-18 06:56:34 +00:00

## Summary In order to make cloudflared behavior more predictable and prevent an exhaustion of resources, we have decided to add session limits that can be configured by the user. This first commit introduces the session limiter and adds it to the UDP handling path. For now the limiter is set to run only in unlimited mode.
78 lines
1.7 KiB
Go
78 lines
1.7 KiB
Go
package session
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
)
|
|
|
|
const (
|
|
unlimitedActiveSessions = 0
|
|
)
|
|
|
|
var (
|
|
ErrTooManyActiveSessions = errors.New("too many active sessions")
|
|
)
|
|
|
|
type Limiter interface {
|
|
// Acquire tries to acquire a free slot for a session, if the value of sessions is already above
|
|
// the maximum it returns ErrTooManyActiveSessions.
|
|
Acquire(sessionType string) error
|
|
// Release releases a slot for a session.
|
|
Release()
|
|
// SetLimit allows to hot swap the limit value of the limiter.
|
|
SetLimit(uint64)
|
|
}
|
|
|
|
type sessionLimiter struct {
|
|
limiterLock sync.Mutex
|
|
activeSessionsCounter uint64
|
|
maxActiveSessions uint64
|
|
unlimited bool
|
|
}
|
|
|
|
func NewLimiter(maxActiveSessions uint64) Limiter {
|
|
sessionLimiter := &sessionLimiter{
|
|
maxActiveSessions: maxActiveSessions,
|
|
unlimited: isUnlimited(maxActiveSessions),
|
|
}
|
|
|
|
return sessionLimiter
|
|
}
|
|
|
|
func (s *sessionLimiter) Acquire(sessionType string) error {
|
|
s.limiterLock.Lock()
|
|
defer s.limiterLock.Unlock()
|
|
|
|
if !s.unlimited && s.activeSessionsCounter >= s.maxActiveSessions {
|
|
sessionRegistrationsDropped.WithLabelValues(sessionType).Inc()
|
|
return ErrTooManyActiveSessions
|
|
}
|
|
|
|
s.activeSessionsCounter++
|
|
return nil
|
|
}
|
|
|
|
func (s *sessionLimiter) Release() {
|
|
s.limiterLock.Lock()
|
|
defer s.limiterLock.Unlock()
|
|
|
|
if s.activeSessionsCounter <= 0 {
|
|
return
|
|
}
|
|
|
|
s.activeSessionsCounter--
|
|
}
|
|
|
|
func (s *sessionLimiter) SetLimit(newMaxActiveSessions uint64) {
|
|
s.limiterLock.Lock()
|
|
defer s.limiterLock.Unlock()
|
|
|
|
s.maxActiveSessions = newMaxActiveSessions
|
|
s.unlimited = isUnlimited(newMaxActiveSessions)
|
|
}
|
|
|
|
// isUnlimited checks if the value received matches the configuration for the unlimited session limiter.
|
|
func isUnlimited(value uint64) bool {
|
|
return value == unlimitedActiveSessions
|
|
}
|