about summary refs log tree commit diff stats
path: root/listenfd/listenfd.go
diff options
context:
space:
mode:
Diffstat (limited to 'listenfd/listenfd.go')
-rw-r--r--listenfd/listenfd.go71
1 files changed, 71 insertions, 0 deletions
diff --git a/listenfd/listenfd.go b/listenfd/listenfd.go
new file mode 100644
index 0000000..cbf3163
--- /dev/null
+++ b/listenfd/listenfd.go
@@ -0,0 +1,71 @@
+package listenfd
+
+import (
+	"crypto/tls"
+	"net"
+	"os"
+	"strconv"
+
+	"go.alanpearce.eu/x/log"
+
+	"gitlab.com/tozd/go/errors"
+)
+
+const fdStart = 3
+
+func GetListener(i uint64, addr string, log *log.Logger) (l net.Listener, err error) {
+	l, err = getFDSocket(i)
+	if err != nil {
+		log.Warn("could not create listener from listenfd", "error", err)
+	}
+
+	log.Debug("listener from listenfd?", "passed", l != nil)
+	if l == nil {
+		l, err = net.Listen("tcp", addr)
+		if err != nil {
+			return nil, errors.Wrap(err, "could not create listener")
+		}
+	}
+
+	return
+}
+
+func GetListenerTLS(
+	i uint64,
+	addr string,
+	config *tls.Config,
+	log *log.Logger,
+) (l net.Listener, err error) {
+	l, err = GetListener(i, addr, log)
+	if err != nil {
+		return nil, err
+	}
+
+	return tls.NewListener(l, config), nil
+}
+
+func getFDSocket(i uint64) (net.Listener, error) {
+	lfds, present := os.LookupEnv("LISTEN_FDS")
+	if !present {
+		return nil, nil
+	}
+	err := os.Unsetenv("LISTEN_FDS")
+	if err != nil {
+		return nil, errors.Wrap(err, "could not unset LISTEN_FDS")
+	}
+
+	fds, err := strconv.ParseUint(lfds, 10, 32)
+	if err != nil {
+		return nil, errors.Wrap(err, "could not parse LISTEN_FDS")
+	}
+	if i >= fds {
+		return nil, errors.Errorf("only %d fds available, requested index %d", fds, i)
+	}
+
+	l, err := net.FileListener(os.NewFile(uintptr(i+fdStart), ""))
+	if err != nil {
+		return nil, errors.Wrap(err, "could not create listener")
+	}
+
+	return l, nil
+}