diff --git a/example_config.yaml b/example_config.yaml index d9eb484..beae654 100644 --- a/example_config.yaml +++ b/example_config.yaml @@ -12,15 +12,6 @@ chihaya: # For more info see: https://prometheus.io prometheus_addr: "0.0.0.0:6880" - # The maximum number of peers returned in an announce. - max_numwant: 50 - - # The default number of peers returned in an announce. - default_numwant: 25 - - # The number of infohashes a single scrape can request before being truncated. - max_scrape_infohashes: 50 - # This block defines configuration for the tracker's HTTP interface. # If you do not wish to run this, delete this section. http: @@ -113,6 +104,9 @@ chihaya: name: memory config: # The frequency which stale peers are removed. + # This balances between + # - collecting garbage more often, potentially using more CPU time, but potentially using less memory (lower value) + # - collecting garbage less frequently, saving CPU time, but keeping old peers long, thus using more memory (higher value). gc_interval: 3m # The amount of time until a peer is considered stale. @@ -132,6 +126,9 @@ chihaya: # name: redis # config: # # The frequency which stale peers are removed. + # # This balances between + # # - collecting garbage more often, potentially using more CPU time, but potentially using less memory (lower value) + # # - collecting garbage less frequently, saving CPU time, but keeping old peers long, thus using more memory (higher value). # gc_interval: 14m # # The frequency which metrics are pushed into a local Prometheus endpoint. diff --git a/frontend/http/frontend.go b/frontend/http/frontend.go index a70319e..43415da 100644 --- a/frontend/http/frontend.go +++ b/frontend/http/frontend.go @@ -100,6 +100,33 @@ func (cfg Config) Validate() Config { } } + if cfg.MaxNumWant <= 0 { + validcfg.MaxNumWant = defaultMaxNumWant + log.Warn("falling back to default configuration", log.Fields{ + "name": "http.MaxNumWant", + "provided": cfg.MaxNumWant, + "default": validcfg.MaxNumWant, + }) + } + + if cfg.DefaultNumWant <= 0 { + validcfg.DefaultNumWant = defaultDefaultNumWant + log.Warn("falling back to default configuration", log.Fields{ + "name": "http.DefaultNumWant", + "provided": cfg.DefaultNumWant, + "default": validcfg.DefaultNumWant, + }) + } + + if cfg.MaxScrapeInfoHashes <= 0 { + validcfg.MaxScrapeInfoHashes = defaultMaxScrapeInfoHashes + log.Warn("falling back to default configuration", log.Fields{ + "name": "http.MaxScrapeInfoHashes", + "provided": cfg.MaxScrapeInfoHashes, + "default": validcfg.MaxScrapeInfoHashes, + }) + } + return validcfg } diff --git a/frontend/http/parser.go b/frontend/http/parser.go index 1d276cb..ca53e87 100644 --- a/frontend/http/parser.go +++ b/frontend/http/parser.go @@ -20,6 +20,13 @@ type ParseOptions struct { MaxScrapeInfoHashes uint32 `yaml:"max_scrape_infohashes"` } +// Default parser config constants. +const ( + defaultMaxNumWant = 100 + defaultDefaultNumWant = 50 + defaultMaxScrapeInfoHashes = 50 +) + // ParseAnnounce parses an bittorrent.AnnounceRequest from an http.Request. func ParseAnnounce(r *http.Request, opts ParseOptions) (*bittorrent.AnnounceRequest, error) { qp, err := bittorrent.ParseURLData(r.RequestURI) diff --git a/frontend/udp/frontend.go b/frontend/udp/frontend.go index a75430e..98f8b75 100644 --- a/frontend/udp/frontend.go +++ b/frontend/udp/frontend.go @@ -46,6 +46,55 @@ func (cfg Config) LogFields() log.Fields { } } +// Validate sanity checks values set in a config and returns a new config with +// default values replacing anything that is invalid. +// +// This function warns to the logger when a value is changed. +func (cfg Config) Validate() Config { + validcfg := cfg + + // Generate a private key if one isn't provided by the user. + if cfg.PrivateKey == "" { + rand.Seed(time.Now().UnixNano()) + pkeyRunes := make([]rune, 64) + for i := range pkeyRunes { + pkeyRunes[i] = allowedGeneratedPrivateKeyRunes[rand.Intn(len(allowedGeneratedPrivateKeyRunes))] + } + validcfg.PrivateKey = string(pkeyRunes) + + log.Warn("UDP private key was not provided, using generated key", log.Fields{"key": validcfg.PrivateKey}) + } + + if cfg.MaxNumWant <= 0 { + validcfg.MaxNumWant = defaultMaxNumWant + log.Warn("falling back to default configuration", log.Fields{ + "name": "udp.MaxNumWant", + "provided": cfg.MaxNumWant, + "default": validcfg.MaxNumWant, + }) + } + + if cfg.DefaultNumWant <= 0 { + validcfg.DefaultNumWant = defaultDefaultNumWant + log.Warn("falling back to default configuration", log.Fields{ + "name": "udp.DefaultNumWant", + "provided": cfg.DefaultNumWant, + "default": validcfg.DefaultNumWant, + }) + } + + if cfg.MaxScrapeInfoHashes <= 0 { + validcfg.MaxScrapeInfoHashes = defaultMaxScrapeInfoHashes + log.Warn("falling back to default configuration", log.Fields{ + "name": "udp.MaxScrapeInfoHashes", + "provided": cfg.MaxScrapeInfoHashes, + "default": validcfg.MaxScrapeInfoHashes, + }) + } + + return validcfg +} + // Frontend holds the state of a UDP BitTorrent Frontend. type Frontend struct { socket *net.UDPConn @@ -60,18 +109,8 @@ type Frontend struct { // NewFrontend creates a new instance of an UDP Frontend that asynchronously // serves requests. -func NewFrontend(logic frontend.TrackerLogic, cfg Config) (*Frontend, error) { - // Generate a private key if one isn't provided by the user. - if cfg.PrivateKey == "" { - rand.Seed(time.Now().UnixNano()) - pkeyRunes := make([]rune, 64) - for i := range pkeyRunes { - pkeyRunes[i] = allowedGeneratedPrivateKeyRunes[rand.Intn(len(allowedGeneratedPrivateKeyRunes))] - } - cfg.PrivateKey = string(pkeyRunes) - - log.Warn("UDP private key was not provided, using generated key", log.Fields{"key": cfg.PrivateKey}) - } +func NewFrontend(logic frontend.TrackerLogic, provided Config) (*Frontend, error) { + cfg := provided.Validate() f := &Frontend{ closing: make(chan struct{}), diff --git a/frontend/udp/parser.go b/frontend/udp/parser.go index b5e4830..96ea9d8 100644 --- a/frontend/udp/parser.go +++ b/frontend/udp/parser.go @@ -58,6 +58,13 @@ type ParseOptions struct { MaxScrapeInfoHashes uint32 `yaml:"max_scrape_infohashes"` } +// Default parser config constants. +const ( + defaultMaxNumWant = 100 + defaultDefaultNumWant = 50 + defaultMaxScrapeInfoHashes = 50 +) + // ParseAnnounce parses an AnnounceRequest from a UDP request. // // If v6Action is true, the announce is parsed the