diff options
-rw-r--r-- | .golangci.yaml | 1 | ||||
-rw-r--r-- | config.go | 3 | ||||
-rw-r--r-- | forge.scfg | 5 | ||||
-rw-r--r-- | lmtp_server.go | 10 | ||||
-rw-r--r-- | main.go | 130 |
5 files changed, 97 insertions, 52 deletions
diff --git a/.golangci.yaml b/.golangci.yaml index 230efcd..760bb07 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -18,6 +18,7 @@ linters: - nestif # e - gocognit # e - gocyclo # e + - dupl # e - cyclop # e - goconst # e - funlen # e @@ -31,6 +31,9 @@ var config struct { Socket string `scfg:"socket"` Execs string `scfg:"execs"` } `scfg:"hooks"` + LMTP struct { + Socket string `scfg:"socket"` + } `scfg:"lmtp"` Git struct { RepoDir string `scfg:"repo_dir"` } `scfg:"git"` @@ -76,3 +76,8 @@ hooks { # Where should hook executables be put? execs /usr/libexec/lindenii/forge/hooks } + +lmtp { + # On which UNIX domain socket should we listen for LMTP on? + socket /var/run/lindenii/forge/lmtp.sock +} diff --git a/lmtp_server.go b/lmtp_server.go new file mode 100644 index 0000000..57f319a --- /dev/null +++ b/lmtp_server.go @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org> + +package main + +import "net" + +func serveLMTP(_ net.Listener) error { + return nil +} @@ -33,72 +33,98 @@ func main() { } // UNIX socket listener for hooks - var hooksListener net.Listener - var err error - hooksListener, err = net.Listen("unix", config.Hooks.Socket) - if errors.Is(err, syscall.EADDRINUSE) { - clog.Warn("Removing existing socket " + config.Hooks.Socket) - if err = syscall.Unlink(config.Hooks.Socket); err != nil { - clog.Fatal(1, "Removing existing socket: "+err.Error()) - } - if hooksListener, err = net.Listen("unix", config.Hooks.Socket); err != nil { + { + hooksListener, err := net.Listen("unix", config.Hooks.Socket) + if errors.Is(err, syscall.EADDRINUSE) { + clog.Warn("Removing existing socket " + config.Hooks.Socket) + if err = syscall.Unlink(config.Hooks.Socket); err != nil { + clog.Fatal(1, "Removing existing socket: "+err.Error()) + } + if hooksListener, err = net.Listen("unix", config.Hooks.Socket); err != nil { + clog.Fatal(1, "Listening hooks: "+err.Error()) + } + } else if err != nil { clog.Fatal(1, "Listening hooks: "+err.Error()) } - } else if err != nil { - clog.Fatal(1, "Listening hooks: "+err.Error()) + clog.Info("Listening hooks on unix " + config.Hooks.Socket) + go func() { + if err = serveGitHooks(hooksListener); err != nil { + clog.Fatal(1, "Serving hooks: "+err.Error()) + } + }() } - clog.Info("Listening hooks on unix " + config.Hooks.Socket) - go func() { - if err = serveGitHooks(hooksListener); err != nil { - clog.Fatal(1, "Serving hooks: "+err.Error()) + + // UNIX socket listener for LMTP + { + lmtpListener, err := net.Listen("unix", config.LMTP.Socket) + if errors.Is(err, syscall.EADDRINUSE) { + clog.Warn("Removing existing socket " + config.LMTP.Socket) + if err = syscall.Unlink(config.LMTP.Socket); err != nil { + clog.Fatal(1, "Removing existing socket: "+err.Error()) + } + if lmtpListener, err = net.Listen("unix", config.LMTP.Socket); err != nil { + clog.Fatal(1, "Listening LMTP: "+err.Error()) + } + } else if err != nil { + clog.Fatal(1, "Listening LMTP: "+err.Error()) } - }() + clog.Info("Listening LMTP on unix " + config.LMTP.Socket) + go func() { + if err = serveLMTP(lmtpListener); err != nil { + clog.Fatal(1, "Serving LMTP: "+err.Error()) + } + }() + } // SSH listener - sshListener, err := net.Listen(config.SSH.Net, config.SSH.Addr) - if errors.Is(err, syscall.EADDRINUSE) && config.SSH.Net == "unix" { - clog.Warn("Removing existing socket " + config.SSH.Addr) - if err = syscall.Unlink(config.SSH.Addr); err != nil { - clog.Fatal(1, "Removing existing socket: "+err.Error()) - } - if sshListener, err = net.Listen(config.SSH.Net, config.SSH.Addr); err != nil { + { + sshListener, err := net.Listen(config.SSH.Net, config.SSH.Addr) + if errors.Is(err, syscall.EADDRINUSE) && config.SSH.Net == "unix" { + clog.Warn("Removing existing socket " + config.SSH.Addr) + if err = syscall.Unlink(config.SSH.Addr); err != nil { + clog.Fatal(1, "Removing existing socket: "+err.Error()) + } + if sshListener, err = net.Listen(config.SSH.Net, config.SSH.Addr); err != nil { + clog.Fatal(1, "Listening SSH: "+err.Error()) + } + } else if err != nil { clog.Fatal(1, "Listening SSH: "+err.Error()) } - } else if err != nil { - clog.Fatal(1, "Listening SSH: "+err.Error()) + clog.Info("Listening SSH on " + config.SSH.Net + " " + config.SSH.Addr) + go func() { + if err = serveSSH(sshListener); err != nil { + clog.Fatal(1, "Serving SSH: "+err.Error()) + } + }() } - clog.Info("Listening SSH on " + config.SSH.Net + " " + config.SSH.Addr) - go func() { - if err = serveSSH(sshListener); err != nil { - clog.Fatal(1, "Serving SSH: "+err.Error()) - } - }() // HTTP listener - httpListener, err := net.Listen(config.HTTP.Net, config.HTTP.Addr) - if errors.Is(err, syscall.EADDRINUSE) && config.HTTP.Net == "unix" { - clog.Warn("Removing existing socket " + config.HTTP.Addr) - if err = syscall.Unlink(config.HTTP.Addr); err != nil { - clog.Fatal(1, "Removing existing socket: "+err.Error()) - } - if httpListener, err = net.Listen(config.HTTP.Net, config.HTTP.Addr); err != nil { + { + httpListener, err := net.Listen(config.HTTP.Net, config.HTTP.Addr) + if errors.Is(err, syscall.EADDRINUSE) && config.HTTP.Net == "unix" { + clog.Warn("Removing existing socket " + config.HTTP.Addr) + if err = syscall.Unlink(config.HTTP.Addr); err != nil { + clog.Fatal(1, "Removing existing socket: "+err.Error()) + } + if httpListener, err = net.Listen(config.HTTP.Net, config.HTTP.Addr); err != nil { + clog.Fatal(1, "Listening HTTP: "+err.Error()) + } + } else if err != nil { clog.Fatal(1, "Listening HTTP: "+err.Error()) } - } else if err != nil { - clog.Fatal(1, "Listening HTTP: "+err.Error()) + server := http.Server{ + Handler: &forgeHTTPRouter{}, + ReadTimeout: time.Duration(config.HTTP.ReadTimeout) * time.Second, + WriteTimeout: time.Duration(config.HTTP.ReadTimeout) * time.Second, + IdleTimeout: time.Duration(config.HTTP.ReadTimeout) * time.Second, + } //exhaustruct:ignore + clog.Info("Listening HTTP on " + config.HTTP.Net + " " + config.HTTP.Addr) + go func() { + if err = server.Serve(httpListener); err != nil && !errors.Is(err, http.ErrServerClosed) { + clog.Fatal(1, "Serving HTTP: "+err.Error()) + } + }() } - server := http.Server{ - Handler: &forgeHTTPRouter{}, - ReadTimeout: time.Duration(config.HTTP.ReadTimeout) * time.Second, - WriteTimeout: time.Duration(config.HTTP.ReadTimeout) * time.Second, - IdleTimeout: time.Duration(config.HTTP.ReadTimeout) * time.Second, - } //exhaustruct:ignore - clog.Info("Listening HTTP on " + config.HTTP.Net + " " + config.HTTP.Addr) - go func() { - if err = server.Serve(httpListener); err != nil && !errors.Is(err, http.ErrServerClosed) { - clog.Fatal(1, "Serving HTTP: "+err.Error()) - } - }() // IRC bot go ircBotLoop() |