From 09ceac3a3684d20610c0466b5fe3223ca77d766f Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Tue, 01 Apr 2025 02:02:35 +0800 Subject: [PATCH] Stub LMTP listener --- .golangci.yaml | 1 + config.go | 3 +++ forge.scfg | 5 +++++ lmtp_server.go | 10 ++++++++++ main.go | 130 ++++++++++++++++++++++++++++++++--------------------- diff --git a/.golangci.yaml b/.golangci.yaml index 230efcd781116576a959a384a388c1afd7edbb14..760bb070945de8aeaff92162d965e6ca45ca981b 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -18,6 +18,7 @@ - maintidx # e - nestif # e - gocognit # e - gocyclo # e + - dupl # e - cyclop # e - goconst # e - funlen # e diff --git a/config.go b/config.go index 1973f3d5b562944e3d22cf2306d73e1b06f8ce85..97e25881463d73898b93b9f7ab658638a446023b 100644 --- a/config.go +++ b/config.go @@ -31,6 +31,9 @@ Hooks 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 5003b759d47016eae606b4dd263c30e802e7db3b..abf4f80a6bd9882019a2396291e76e1f40be4f38 100644 --- a/forge.scfg +++ b/forge.scfg @@ -76,3 +76,8 @@ # 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 0000000000000000000000000000000000000000..57f319a680acda4a440259bc5353177de2c81a73 --- /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 90a0bac19a622cbd14bab818987ec1f57009c40f..75e187fcfe1b31b585e932eb194749e3f3c1cc9e 100644 --- a/main.go +++ b/main.go @@ -33,72 +33,98 @@ clog.Fatal(1, "Loading templates: "+err.Error()) } // 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() -- 2.48.1