mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 18:37:26 +08:00
60 lines
1.0 KiB
Go
60 lines
1.0 KiB
Go
package data
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/libp2p/go-libp2p/core/peer"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
type RateLimiter struct {
|
|
mu sync.RWMutex
|
|
clients map[peer.ID]time.Time
|
|
maxTokens int
|
|
windowSize time.Duration
|
|
}
|
|
|
|
type bucket struct {
|
|
tokens int
|
|
lastSeen time.Time
|
|
}
|
|
|
|
func NewRateLimiter(
|
|
maxTokens int,
|
|
windowSize time.Duration,
|
|
) *RateLimiter {
|
|
return &RateLimiter{
|
|
clients: make(map[peer.ID]time.Time),
|
|
maxTokens: maxTokens,
|
|
windowSize: windowSize,
|
|
}
|
|
}
|
|
|
|
func (rl *RateLimiter) Allow(peerId peer.ID) error {
|
|
rl.mu.Lock()
|
|
defer rl.mu.Unlock()
|
|
|
|
now := time.Now()
|
|
|
|
windowStart := now.Add(-rl.windowSize)
|
|
|
|
for peerId, time := range rl.clients {
|
|
if time.Before(windowStart) {
|
|
delete(rl.clients, peerId)
|
|
}
|
|
}
|
|
|
|
if _, exists := rl.clients[peerId]; !exists {
|
|
if len(rl.clients) >= rl.maxTokens {
|
|
return status.Errorf(codes.ResourceExhausted,
|
|
"maximum number of unique callers (%d) reached", rl.maxTokens)
|
|
}
|
|
}
|
|
|
|
rl.clients[peerId] = now
|
|
|
|
return nil
|
|
}
|