Files
crockery/internal/services/services.go

70 lines
1.3 KiB
Go

package services
import (
"context"
"io"
"log"
"ur.gs/crockery/internal/imap"
"ur.gs/crockery/internal/smtp"
"ur.gs/crockery/internal/store"
)
type Interface interface {
Run() // Run the services
}
func New(ctx context.Context, datastore store.Interface) (Interface, error) {
ctx, cancelFunc := context.WithCancel(ctx)
return &concrete{
ctx: ctx,
cancel: cancelFunc,
store: datastore,
}, nil
}
type genServer interface {
Run()
io.Closer
}
type concrete struct {
ctx context.Context
cancel context.CancelFunc
store store.Interface
// This is only mutated in the Run() method
servers []genServer
}
// For now, bind unconditionally to these ports, on IPv4 + IPv6:
// 25 - SMTP+MTA (STARTTLS)
// 587 - SMTP+MSA (STARTTLS)
// 143 - IMAP (STARTTLS)
// 993 - IMAP (TLS)
//
// Each listener gets incoming connections serviced against the passed-in store.
func (c *concrete) Run() {
c.servers = []genServer{
smtp.NewMTA(c.cancel, c.store),
smtp.NewMSA(c.cancel, c.store),
imap.NewServer(c.cancel, c.store, false),
imap.NewServer(c.cancel, c.store, true),
}
log.Print("Running all services")
for _, srv := range c.servers {
go srv.Run()
}
<-c.ctx.Done()
log.Print("Closing all services")
for _, srv := range c.servers {
srv.Close()
}
}