summaryrefslogtreecommitdiff
path: root/listeners.go
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-03-26 15:45:51 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2019-03-26 15:45:51 -0600
commit86e2d1b0a48fbd84590291969611f1870471c3e0 (patch)
treed3a8d82ca88f7d7ff60476cd772d8c4314cd6a3f /listeners.go
parent859b5d7ea3b8f660ac68d9aea5a53d25a9a7422c (diff)
Rudimentary start of HTTP servers
Diffstat (limited to 'listeners.go')
-rw-r--r--listeners.go51
1 files changed, 51 insertions, 0 deletions
diff --git a/listeners.go b/listeners.go
new file mode 100644
index 0000000..962cb1d
--- /dev/null
+++ b/listeners.go
@@ -0,0 +1,51 @@
+package caddy2
+
+import (
+ "fmt"
+ "net"
+ "sync/atomic"
+)
+
+// Listen returns a listener suitable for use in a Caddy module.
+func Listen(proto, addr string) (net.Listener, error) {
+ ln, err := net.Listen(proto, addr)
+ if err != nil {
+ return nil, err
+ }
+ return &fakeCloseListener{Listener: ln}, nil
+}
+
+// fakeCloseListener's Close() method is a no-op. This allows
+// stopping servers that are using the listener without giving
+// up the socket; thus, servers become hot-swappable while the
+// listener remains running. Listeners should be re-wrapped in
+// a new fakeCloseListener each time the listener is reused.
+type fakeCloseListener struct {
+ closed int32
+ net.Listener
+}
+
+// Accept accepts connections until Close() is called.
+func (fcl *fakeCloseListener) Accept() (net.Conn, error) {
+ if atomic.LoadInt32(&fcl.closed) == 1 {
+ return nil, ErrSwappingServers
+ }
+ return fcl.Listener.Accept()
+}
+
+// Close stops accepting new connections, but does not
+// actually close the underlying listener.
+func (fcl *fakeCloseListener) Close() error {
+ atomic.StoreInt32(&fcl.closed, 1)
+ return nil
+}
+
+// CloseUnderlying actually closes the underlying listener.
+func (fcl *fakeCloseListener) CloseUnderlying() error {
+ return fcl.Listener.Close()
+}
+
+// ErrSwappingServers is returned by fakeCloseListener when
+// Close() is called, indicating that it is pretending to
+// be closed so that the server using it can terminate.
+var ErrSwappingServers = fmt.Errorf("listener 'closed' 😉")