From 09ceac3a3684d20610c0466b5fe3223ca77d766f Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Tue, 1 Apr 2025 02:02:35 +0800 Subject: Stub LMTP listener --- .golangci.yaml | 1 + config.go | 3 ++ forge.scfg | 5 +++ lmtp_server.go | 10 +++++ main.go | 130 ++++++++++++++++++++++++++++++++++----------------------- 5 files changed, 97 insertions(+), 52 deletions(-) create mode 100644 lmtp_server.go 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 diff --git a/config.go b/config.go index 1973f3d..97e2588 100644 --- a/config.go +++ b/config.go @@ -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"` diff --git a/forge.scfg b/forge.scfg index 5003b75..abf4f80 100644 --- a/forge.scfg +++ b/forge.scfg @@ -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 + +package main + +import "net" + +func serveLMTP(_ net.Listener) error { + return nil +} diff --git a/main.go b/main.go index 90a0bac..75e187f 100644 --- a/main.go +++ b/main.go @@ -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() -- cgit v1.2.3