maddy/maddy.go

121 lines
2.8 KiB
Go

package maddy
import (
"errors"
"fmt"
"io"
"log"
"os"
"os/signal"
"syscall"
"github.com/emersion/maddy/module"
"github.com/mholt/caddy/caddyfile"
)
var Directives []string
func Start(cfg []caddyfile.ServerBlock) error {
var instances []module.Module
for _, block := range cfg {
if len(block.Keys) != 2 {
return fmt.Errorf("wanted 2 keys in module instance definition, got %d (%v)", len(block.Keys), block.Keys)
}
modName := block.Keys[0]
instName := block.Keys[1]
factory := module.GetMod(modName)
if factory == nil {
return fmt.Errorf("unknown module: %s", modName)
}
if module.GetInstance(instName) != nil {
return fmt.Errorf("module instance named %s already exists", instName)
}
inst, err := factory(instName, block.Tokens)
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()
}
}
module.WaitGroup.Wait()
return nil
}
func authProvider(tokens []caddyfile.Token) (module.AuthProvider, error) {
var authName string
var ok bool
d := caddyfile.NewDispenserTokens("", tokens)
d.Next()
args := d.RemainingArgs()
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(tokens []caddyfile.Token) (module.Storage, error) {
var authName string
var ok bool
d := caddyfile.NewDispenserTokens("", tokens)
d.Next()
args := d.RemainingArgs()
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 oneStringValue(tokens []caddyfile.Token) string {
d := caddyfile.NewDispenserTokens("", tokens)
d.Next()
args := d.RemainingArgs()
if len(args) == 0 {
return ""
}
return args[0]
}