mirror of
https://github.com/ergochat/ergo.git
synced 2025-12-08 17:07:36 +01:00
implement FAIL METADATA RATE_LIMITED
This commit is contained in:
parent
96aa018352
commit
0119bbc36f
@ -1111,6 +1111,11 @@ metadata:
|
||||
max-subs: 100
|
||||
# how many keys can be stored per entity?
|
||||
max-keys: 100
|
||||
# rate limiting for client metadata updates, which are expensive to process
|
||||
client-throttle:
|
||||
enabled: true
|
||||
duration: 2m
|
||||
max-attempts: 10
|
||||
|
||||
# experimental support for mobile push notifications
|
||||
# see the manual for potential security, privacy, and performance implications.
|
||||
|
||||
@ -130,6 +130,7 @@ type Client struct {
|
||||
pushSubscriptionsExist atomic.Uint32 // this is a cache on len(pushSubscriptions) != 0
|
||||
pushQueue pushQueue
|
||||
metadata map[string]string
|
||||
metadataThrottle connection_limits.ThrottleDetails
|
||||
}
|
||||
|
||||
type saslStatus struct {
|
||||
|
||||
@ -734,10 +734,11 @@ type Config struct {
|
||||
}
|
||||
|
||||
Metadata struct {
|
||||
Enabled bool
|
||||
MaxSubs int `yaml:"max-subs"`
|
||||
MaxKeys int `yaml:"max-keys"`
|
||||
MaxValueBytes int `yaml:"max-value-length"`
|
||||
Enabled bool
|
||||
MaxSubs int `yaml:"max-subs"`
|
||||
MaxKeys int `yaml:"max-keys"`
|
||||
MaxValueBytes int `yaml:"max-value-length"`
|
||||
ClientThrottle ThrottleConfig `yaml:"client-throttle"`
|
||||
}
|
||||
|
||||
WebPush struct {
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ergochat/ergo/irc/caps"
|
||||
"github.com/ergochat/ergo/irc/connection_limits"
|
||||
"github.com/ergochat/ergo/irc/languages"
|
||||
"github.com/ergochat/ergo/irc/modes"
|
||||
"github.com/ergochat/ergo/irc/utils"
|
||||
@ -1039,3 +1040,22 @@ func (client *Client) CountMetadata() int {
|
||||
|
||||
return len(client.metadata)
|
||||
}
|
||||
|
||||
func (client *Client) checkMetadataThrottle() (throttled bool, remainingTime time.Duration) {
|
||||
config := client.server.Config()
|
||||
if !config.Metadata.ClientThrottle.Enabled {
|
||||
return false, 0
|
||||
}
|
||||
|
||||
client.stateMutex.Lock()
|
||||
defer client.stateMutex.Unlock()
|
||||
|
||||
// copy client.metadataThrottle locally and then back for processing
|
||||
var throttle connection_limits.GenericThrottle
|
||||
throttle.ThrottleDetails = client.metadataThrottle
|
||||
throttle.Duration = config.Metadata.ClientThrottle.Duration
|
||||
throttle.Limit = config.Metadata.ClientThrottle.MaxAttempts
|
||||
throttled, remainingTime = throttle.Touch()
|
||||
client.metadataThrottle = throttle.ThrottleDetails
|
||||
return
|
||||
}
|
||||
|
||||
@ -3197,6 +3197,18 @@ func metadataRegisteredHandler(client *Client, config *Config, subcommand string
|
||||
return
|
||||
}
|
||||
|
||||
// only rate limit clients changing their own metadata:
|
||||
// channel metadata updates are not any more costly than a PRIVMSG
|
||||
if client == targetClient {
|
||||
if throttled, remainingTime := client.checkMetadataThrottle(); throttled {
|
||||
retryAfter := strconv.Itoa(int(remainingTime.Seconds()) + 1)
|
||||
rb.Add(nil, server.name, "FAIL", "METADATA", "RATE_LIMITED",
|
||||
target, utils.SafeErrorParam(key), retryAfter,
|
||||
fmt.Sprintf(client.t("Please wait at least %v and try again"), remainingTime.Round(time.Millisecond)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(params) > 3 {
|
||||
value := params[3]
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ var (
|
||||
errMetadataNotFound = errors.New("key not found")
|
||||
)
|
||||
|
||||
type MetadataHaver = interface {
|
||||
type MetadataHaver interface {
|
||||
SetMetadata(key string, value string, limit int) (updated bool, err error)
|
||||
GetMetadata(key string) (string, bool)
|
||||
DeleteMetadata(key string) (updated bool)
|
||||
|
||||
@ -183,12 +183,13 @@ const (
|
||||
RPL_MONLIST = "732"
|
||||
RPL_ENDOFMONLIST = "733"
|
||||
ERR_MONLISTFULL = "734"
|
||||
RPL_KEYVALUE = "761" // metadata numerics
|
||||
RPL_WHOISKEYVALUE = "760" // metadata numerics
|
||||
RPL_KEYVALUE = "761"
|
||||
RPL_KEYNOTSET = "766"
|
||||
RPL_METADATASUBOK = "770"
|
||||
RPL_METADATAUNSUBOK = "771"
|
||||
RPL_METADATASUBS = "772"
|
||||
RPL_METADATASYNCLATER = "774"
|
||||
RPL_METADATASYNCLATER = "774" // end metadata numerics
|
||||
RPL_LOGGEDIN = "900"
|
||||
RPL_LOGGEDOUT = "901"
|
||||
ERR_NICKLOCKED = "902"
|
||||
|
||||
@ -1082,6 +1082,11 @@ metadata:
|
||||
max-subs: 100
|
||||
# how many keys can be stored per entity?
|
||||
max-keys: 100
|
||||
# rate limiting for client metadata updates, which are expensive to process
|
||||
client-throttle:
|
||||
enabled: true
|
||||
duration: 2m
|
||||
max-attempts: 10
|
||||
|
||||
# experimental support for mobile push notifications
|
||||
# see the manual for potential security, privacy, and performance implications.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user