Expand upon flood detection and chat rate limiting. Closes #1349
This commit is contained in:
parent
99a3aae843
commit
e3b0af1b67
@ -25,6 +25,8 @@ type ChatClient struct {
|
||||
// Buffered channel of outbound messages.
|
||||
send chan []byte
|
||||
rateLimiter *rate.Limiter
|
||||
timeoutTimer *time.Timer
|
||||
inTimeout bool
|
||||
Geo *geoip.GeoDetails `json:"geo"`
|
||||
MessageCount int `json:"messageCount"`
|
||||
UserAgent string `json:"userAgent"`
|
||||
@ -72,7 +74,9 @@ func (c *ChatClient) sendConnectedClientInfo() {
|
||||
}
|
||||
|
||||
func (c *ChatClient) readPump() {
|
||||
c.rateLimiter = rate.NewLimiter(0.6, 5)
|
||||
// Allow 3 messages every two seconds.
|
||||
limit := rate.Every(2 * time.Second / 3)
|
||||
c.rateLimiter = rate.NewLimiter(limit, 1)
|
||||
|
||||
defer func() {
|
||||
c.close()
|
||||
@ -100,8 +104,16 @@ func (c *ChatClient) readPump() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if this client is temporarily blocked from sending messages.
|
||||
if c.inTimeout {
|
||||
continue
|
||||
}
|
||||
|
||||
// Guard against floods.
|
||||
if !c.passesRateLimit() {
|
||||
log.Warnln("Client", c.id, c.User.DisplayName, "has exceeded the messaging rate limiting thresholds and messages are being rejected temporarily.")
|
||||
c.startChatRejectionTimeout()
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@ -171,12 +183,24 @@ func (c *ChatClient) close() {
|
||||
}
|
||||
|
||||
func (c *ChatClient) passesRateLimit() bool {
|
||||
if !c.rateLimiter.Allow() {
|
||||
log.Debugln("Client", c.id, c.User.DisplayName, "has exceeded the messaging rate limiting thresholds.")
|
||||
return false
|
||||
return c.rateLimiter.Allow() && !c.inTimeout
|
||||
}
|
||||
|
||||
func (c *ChatClient) startChatRejectionTimeout() {
|
||||
if c.timeoutTimer != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return true
|
||||
c.inTimeout = true
|
||||
c.timeoutTimer = time.NewTimer(10 * time.Second)
|
||||
go func(c *ChatClient) {
|
||||
for range c.timeoutTimer.C {
|
||||
c.inTimeout = false
|
||||
c.timeoutTimer = nil
|
||||
}
|
||||
}(c)
|
||||
|
||||
c.sendAction("You are temporarily blocked from sending chat messages due to perceived flooding.")
|
||||
}
|
||||
|
||||
func (c *ChatClient) sendPayload(payload events.EventPayload) {
|
||||
|
Loading…
Reference in New Issue
Block a user