diff --git a/module/module.go b/module/module.go new file mode 100644 index 0000000..c84100a --- /dev/null +++ b/module/module.go @@ -0,0 +1,36 @@ +// Package module contians interfaces implemented by maddy modules. +// +// They are moved to separate package to prevent circular dependencies. +// +// Each interface required by maddy for operation is provided by some object +// called "module". This includes authentication, storage backends, DKIM, +// email filters, etc. Each module may serve multiple functions. I.e. it can +// be IMAP storage backend, SMTP upstream and authentication provider at the +// same moment. +// +// Each module gets its own unique name (sqlmail for go-sqlmail, proxy for +// proxy module, local for local delivery perhaps, etc). Each module instance +// also gets its own (unique too) name which is used to refer to it in +// configuration. +package module + +import "github.com/mholt/caddy/caddyfile" + +// Module is the interface implemented by all maddy module instances. +// +// It defines basic methods used to identify instances. +type Module interface { + // Name method reports module name. + // + // It is used to reference module in the configuration and in logs. + Name() string + + // InstanceName method reports unique name of this module instance. + InstanceName() string + + // Module version. Reported in logs. + Version() string +} + +// NewModule is function that creates new instance of module with specified name. +type NewModule func(name string, cfg map[string]caddyfile.Token) (Module, error) diff --git a/module/registry.go b/module/registry.go new file mode 100644 index 0000000..9722d91 --- /dev/null +++ b/module/registry.go @@ -0,0 +1,63 @@ +package module + +import "sync" + +var modules = make(map[string]NewModule) +var modulesLck sync.RWMutex + +// Register adds module factory function to global registry. +// +// name must be unique. Register will panic if module with specified name +// already exists in registry. +// +// You probably want to call this function from func init() of module package. +func Register(name string, factory NewModule) { + modulesLck.Lock() + defer modulesLck.Unlock() + + if _, ok := modules[name]; ok { + panic("Register: module with specified name is already registered: " + name) + } + + modules[name] = factory +} + +// GetMod returns module from global registry. +// +// Nil is returned if no module with specified name is registered. +func GetMod(name string) NewModule { + modulesLck.RLock() + defer modulesLck.RUnlock() + + return modules[name] +} + +var instances = make(map[string]Module) +var instancesLck sync.RWMutex + +// Register adds module factory function to global registry. +// +// name must be unique. Register will panic if module with specified name +// already exists in registry. +// +// You probably want to call this function from func init() of module package. +func RegisterInstance(inst Module) { + instancesLck.Lock() + defer instancesLck.Unlock() + + if _, ok := instances[inst.InstanceName()]; ok { + panic("RegisterInstance: instance with specified name is already registered: " + inst.InstanceName()) + } + + instances[inst.InstanceName()] = inst +} + +// GetInstance returns module instance from global registry. +// +// Nil is returned if no module instance with specified name is registered. +func GetInstnace(name string) Module { + instancesLck.RLock() + defer instancesLck.RUnlock() + + return instances[name] +}