mirror of
https://github.com/foxcpp/maddy.git
synced 2025-04-04 21:47:40 +03:00
This allows to set hostname or tls for all modules, making it possible slightly cleaner configuration.
138 lines
3.2 KiB
Go
138 lines
3.2 KiB
Go
package maddy
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"github.com/emersion/maddy/config"
|
|
"github.com/emersion/maddy/module"
|
|
)
|
|
|
|
func Start(cfg []config.Node) error {
|
|
instances := make([]module.Module, 0, len(cfg))
|
|
globalCfg := make(map[string][]string)
|
|
for _, block := range cfg {
|
|
switch block.Name {
|
|
case "tls":
|
|
if len(block.Args) == 1 && block.Args[0] == "off" {
|
|
log.Println("TLS is disabled, this is insecure configuration and should be used only for testing!")
|
|
}
|
|
fallthrough
|
|
case "hostname":
|
|
globalCfg[block.Name] = block.Args
|
|
continue
|
|
}
|
|
|
|
var instName string
|
|
if len(block.Args) == 0 {
|
|
instName = block.Name
|
|
} else {
|
|
instName = block.Args[0]
|
|
}
|
|
|
|
modName := block.Name
|
|
|
|
factory := module.GetMod(modName)
|
|
if factory == nil {
|
|
return fmt.Errorf("unknown module: %s", modName)
|
|
}
|
|
|
|
if mod := module.GetInstance(instName); mod != nil {
|
|
if !strings.HasPrefix(instName, "default") {
|
|
return fmt.Errorf("module instance named %s already exists", instName)
|
|
}
|
|
|
|
// Clean up default module before replacing it.
|
|
if closer, ok := mod.(io.Closer); ok {
|
|
closer.Close()
|
|
}
|
|
}
|
|
|
|
inst, err := factory(instName, globalCfg, block)
|
|
if err != nil {
|
|
return fmt.Errorf("module instance %s initialization failed: %v", instName, err)
|
|
}
|
|
|
|
module.RegisterInstance(inst)
|
|
instances = append(instances, inst)
|
|
}
|
|
|
|
sig := make(chan os.Signal, 5)
|
|
signal.Notify(sig, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGINT)
|
|
|
|
s := <-sig
|
|
log.Printf("signal received (%v), next signal will force immediate shutdown.\n", s)
|
|
go func() {
|
|
s := <-sig
|
|
log.Printf("forced shutdown due to signal (%v)!\n", s)
|
|
os.Exit(1)
|
|
}()
|
|
|
|
for _, inst := range instances {
|
|
if closer, ok := inst.(io.Closer); ok {
|
|
closer.Close()
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func authProvider(args []string) (module.AuthProvider, error) {
|
|
if len(args) != 1 {
|
|
return nil, errors.New("auth: expected 1 argument")
|
|
}
|
|
|
|
authName := args[0]
|
|
authMod := module.GetInstance(authName)
|
|
if authMod == nil {
|
|
return nil, fmt.Errorf("unknown auth. provider instance: %s", authName)
|
|
}
|
|
|
|
provider, ok := authMod.(module.AuthProvider)
|
|
if !ok {
|
|
return nil, fmt.Errorf("module %s doesn't implements auth. provider interface", authMod.Name())
|
|
}
|
|
return provider, nil
|
|
}
|
|
|
|
func storageBackend(args []string) (module.Storage, error) {
|
|
if len(args) != 1 {
|
|
return nil, errors.New("storage: expected 1 argument")
|
|
}
|
|
|
|
authName := args[0]
|
|
authMod := module.GetInstance(authName)
|
|
if authMod == nil {
|
|
return nil, fmt.Errorf("unknown storage backend instance: %s", authName)
|
|
}
|
|
|
|
provider, ok := authMod.(module.Storage)
|
|
if !ok {
|
|
return nil, fmt.Errorf("module %s doesn't implements storage interface", authMod.Name())
|
|
}
|
|
return provider, nil
|
|
}
|
|
|
|
func deliveryTarget(args []string) (module.DeliveryTarget, error) {
|
|
if len(args) != 1 {
|
|
return nil, errors.New("delivery: expected 1 argument")
|
|
}
|
|
|
|
modName := args[0]
|
|
mod := module.GetInstance(modName)
|
|
if mod == nil {
|
|
return nil, fmt.Errorf("unknown delivery target instance: %s", modName)
|
|
}
|
|
|
|
target, ok := mod.(module.DeliveryTarget)
|
|
if !ok {
|
|
return nil, fmt.Errorf("module %s doesn't implements delivery target interface", mod.Name())
|
|
}
|
|
return target, nil
|
|
}
|