diff --git a/config.go b/config.go index 1016566..eb26b24 100644 --- a/config.go +++ b/config.go @@ -18,8 +18,8 @@ var DefaultConfig = Config{ Tracker: TrackerConfig{ AnnounceInterval: 30 * time.Minute, MinAnnounceInterval: 20 * time.Minute, - AnnounceMiddleware: []string{}, - ScrapeMiddleware: []string{}, + AnnounceMiddleware: []MiddlewareConfig{}, + ScrapeMiddleware: []MiddlewareConfig{}, }, Servers: []ServerConfig{}, } @@ -33,10 +33,17 @@ type Config struct { // TrackerConfig represents the configuration of protocol-agnostic BitTorrent // Tracker used by Servers started by chihaya. type TrackerConfig struct { - AnnounceInterval time.Duration `yaml:"announce"` - MinAnnounceInterval time.Duration `yaml:"min_announce"` - AnnounceMiddleware []string `yaml:"announce_middleware"` - ScrapeMiddleware []string `yaml:"scrape_middleware"` + AnnounceInterval time.Duration `yaml:"announce"` + MinAnnounceInterval time.Duration `yaml:"min_announce"` + AnnounceMiddleware []MiddlewareConfig `yaml:"announce_middleware"` + ScrapeMiddleware []MiddlewareConfig `yaml:"scrape_middleware"` +} + +// MiddlewareConfig represents the configuration of a middleware used by +// the tracker. +type MiddlewareConfig struct { + Name string `yaml:"name"` + Config interface{} `yaml:"config"` } // ServerConfig represents the configuration of the Servers started by chihaya. diff --git a/config_example.yaml b/config_example.yaml index 4114da9..db62393 100644 --- a/config_example.yaml +++ b/config_example.yaml @@ -8,13 +8,15 @@ chihaya: min_announce: 5m announce_middleware: # These are currently fake values - - prometheus - - store_client_validation - - store_create_on_announce + - name: prometheus + - name: store_client_validation + config: + be_clever: true + - name: store_create_on_announce scrape_middleware: # These are currently fake values - - prometheus - - store_client_validation + - name: prometheus + - name: store_client_validation servers: - name: store diff --git a/tracker/middleware.go b/tracker/middleware.go index 995506b..6202b06 100644 --- a/tracker/middleware.go +++ b/tracker/middleware.go @@ -14,6 +14,10 @@ type AnnounceHandler func(*chihaya.TrackerConfig, *chihaya.AnnounceRequest, *chi // of AnnounceHandlers. type AnnounceMiddleware func(AnnounceHandler) AnnounceHandler +// AnnounceMiddlewareConstructor is a function that creates a new +// AnnounceMiddleware from a MiddlewareConfig. +type AnnounceMiddlewareConstructor func(chihaya.MiddlewareConfig) AnnounceMiddleware + type announceChain struct{ mw []AnnounceMiddleware } func (c *announceChain) Append(mw ...AnnounceMiddleware) { @@ -31,23 +35,39 @@ func (c *announceChain) Handler() AnnounceHandler { return final } -var announceMiddleware = make(map[string]AnnounceMiddleware) +var announceMiddlewareConstructors = make(map[string]AnnounceMiddlewareConstructor) + +// RegisterAnnounceMiddlewareConstructor makes a configurable middleware +// globally available under the provided name. +// +// If this function is called twice with the same name or if the constructor is +// nil, it panics. +func RegisterAnnounceMiddlewareConstructor(name string, mw AnnounceMiddlewareConstructor) { + if mw == nil { + panic("tracker: could not register nil AnnounceMiddlewareConstructor") + } + + if _, dup := announceMiddlewareConstructors[name]; dup { + panic("tracker: could not register duplicate AnnounceMiddleware: " + name) + } + + announceMiddlewareConstructors[name] = mw +} // RegisterAnnounceMiddleware makes a middleware globally available under the -// provided named. +// provided name. // -// If this function is called twice with the same name or if the handler is nil, -// it panics. +// This function is intended to register middleware that has no configuration. +// If this function is called twice with the same name or if the middleware is +// nil, it panics. func RegisterAnnounceMiddleware(name string, mw AnnounceMiddleware) { if mw == nil { panic("tracker: could not register nil AnnounceMiddleware") } - if _, dup := announceMiddleware[name]; dup { - panic("tracker: could not register duplicate AnnounceMiddleware: " + name) - } - - announceMiddleware[name] = mw + RegisterAnnounceMiddlewareConstructor(name, func(_ chihaya.MiddlewareConfig) AnnounceMiddleware { + return mw + }) } // ScrapeHandler is a function that operates on a ScrapeResponse before it has @@ -58,6 +78,10 @@ type ScrapeHandler func(*chihaya.TrackerConfig, *chihaya.ScrapeRequest, *chihaya // ScrapeHandlers. type ScrapeMiddleware func(ScrapeHandler) ScrapeHandler +// ScrapeMiddlewareConstructor is a function that creates a new +// ScrapeMiddleware from a MiddlewareConfig. +type ScrapeMiddlewareConstructor func(chihaya.MiddlewareConfig) ScrapeMiddleware + type scrapeChain struct{ mw []ScrapeMiddleware } func (c *scrapeChain) Append(mw ...ScrapeMiddleware) { @@ -74,21 +98,37 @@ func (c *scrapeChain) Handler() ScrapeHandler { return final } -var scrapeMiddleware = make(map[string]ScrapeMiddleware) +var scrapeMiddlewareConstructors = make(map[string]ScrapeMiddlewareConstructor) + +// RegisterScrapeMiddlewareConstructor makes a configurable middleware globally +// available under the provided name. +// +// If this function is called twice with the same name or if the constructor is +// nil, it panics. +func RegisterScrapeMiddlewareConstructor(name string, mw ScrapeMiddlewareConstructor) { + if mw == nil { + panic("tracker: could not register nil ScrapeMiddlewareConstructor") + } + + if _, dup := scrapeMiddlewareConstructors[name]; dup { + panic("tracker: could not register duplicate ScrapeMiddleware: " + name) + } + + scrapeMiddlewareConstructors[name] = mw +} // RegisterScrapeMiddleware makes a middleware globally available under the -// provided named. +// provided name. // -// If this function is called twice with the same name or if the handler is nil, -// it panics. +// This function is intended to register middleware that has no configuration. +// If this function is called twice with the same name or if the middleware is +// nil, it panics. func RegisterScrapeMiddleware(name string, mw ScrapeMiddleware) { if mw == nil { panic("tracker: could not register nil ScrapeMiddleware") } - if _, dup := scrapeMiddleware[name]; dup { - panic("tracker: could not register duplicate ScrapeMiddleware: " + name) - } - - scrapeMiddleware[name] = mw + RegisterScrapeMiddlewareConstructor(name, func(_ chihaya.MiddlewareConfig) ScrapeMiddleware { + return mw + }) } diff --git a/tracker/tracker.go b/tracker/tracker.go index e4cc7b2..a5c829a 100644 --- a/tracker/tracker.go +++ b/tracker/tracker.go @@ -31,21 +31,21 @@ type Tracker struct { // in the provided configuration. func NewTracker(cfg *chihaya.TrackerConfig) (*Tracker, error) { var achain announceChain - for _, mwName := range cfg.AnnounceMiddleware { - mw, ok := announceMiddleware[mwName] + for _, mwConfig := range cfg.AnnounceMiddleware { + mw, ok := announceMiddlewareConstructors[mwConfig.Name] if !ok { - return nil, errors.New("failed to find announce middleware: " + mwName) + return nil, errors.New("failed to find announce middleware: " + mwConfig.Name) } - achain.Append(mw) + achain.Append(mw(mwConfig)) } var schain scrapeChain - for _, mwName := range cfg.ScrapeMiddleware { - mw, ok := scrapeMiddleware[mwName] + for _, mwConfig := range cfg.ScrapeMiddleware { + mw, ok := scrapeMiddlewareConstructors[mwConfig.Name] if !ok { - return nil, errors.New("failed to find scrape middleware: " + mwName) + return nil, errors.New("failed to find scrape middleware: " + mwConfig.Name) } - schain.Append(mw) + schain.Append(mw(mwConfig)) } return &Tracker{