]> Cypherpunks repositories - gostls13.git/commitdiff
net: add KeepAlive field to ListenConfig
authorLeo Antunes <leo@costela.net>
Thu, 4 Apr 2019 08:50:27 +0000 (08:50 +0000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 4 Apr 2019 14:51:33 +0000 (14:51 +0000)
This commit adds a KeepAlive field to ListenConfig and uses it
analogously to Dialer.KeepAlive to set TCP KeepAlives per default on
Accept()

Fixes #23378

Change-Id: I57eaf9508c979e7f0e2b8c5dd8e8901f6eb27fd6
GitHub-Last-Rev: e9e035d53ee8aa3d899d12db08b293f599daecb6
GitHub-Pull-Request: golang/go#31242
Reviewed-on: https://go-review.googlesource.com/c/go/+/170678
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/net/dial.go
src/net/file_plan9.go
src/net/file_unix.go
src/net/http/server.go
src/net/tcpsock.go
src/net/tcpsock_plan9.go
src/net/tcpsock_posix.go

index 1dd8690739ef64a79c31d5bf58557c1e3c764800..1f3ce1dfa323ea8c4759f0e6421de59b4287c1f9 100644 (file)
@@ -596,6 +596,14 @@ type ListenConfig struct {
        // necessarily the ones passed to Listen. For example, passing "tcp" to
        // Listen will cause the Control function to be called with "tcp4" or "tcp6".
        Control func(network, address string, c syscall.RawConn) error
+
+       // KeepAlive specifies the keep-alive period for network
+       // connections accepted by this listener.
+       // If zero, keep-alives are enabled if supported by the protocol
+       // and operating system. Network protocols or operating systems
+       // that do not support keep-alives ignore this field.
+       // If negative, keep-alives are disabled.
+       KeepAlive time.Duration
 }
 
 // Listen announces on the local network address.
index d16e5a166c356635f2fa2e084d30dbcb44339e57..dfb23d2e8424d0fe5213a4fb65e9cbbd6cefb52f 100644 (file)
@@ -127,7 +127,7 @@ func fileListener(f *os.File) (Listener, error) {
                return nil, errors.New("file does not represent a listener")
        }
 
-       return &TCPListener{fd}, nil
+       return &TCPListener{fd: fd}, nil
 }
 
 func filePacketConn(f *os.File) (PacketConn, error) {
index 452a079bfc5b86d98c0ae7a40b110393a59dec6d..dba69554ca79f4e224c8bcaf3b067123419242d1 100644 (file)
@@ -93,7 +93,7 @@ func fileListener(f *os.File) (Listener, error) {
        }
        switch laddr := fd.laddr.(type) {
        case *TCPAddr:
-               return &TCPListener{fd}, nil
+               return &TCPListener{fd: fd}, nil
        case *UnixAddr:
                return &UnixListener{fd: fd, path: laddr.Name, unlink: false}, nil
        }
index 4e9ea34491743f5409a6f8606601b0ceb03209e8..14f74285c12adc8fb10117d6c5835376a4fa6cfd 100644 (file)
@@ -2792,7 +2792,7 @@ func (srv *Server) ListenAndServe() error {
        if err != nil {
                return err
        }
-       return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
+       return srv.Serve(ln)
 }
 
 var testHookServerServe func(*Server, net.Listener) // used if non-nil
@@ -3076,7 +3076,7 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
 
        defer ln.Close()
 
-       return srv.ServeTLS(tcpKeepAliveListener{ln.(*net.TCPListener)}, certFile, keyFile)
+       return srv.ServeTLS(ln, certFile, keyFile)
 }
 
 // setupHTTP2_ServeTLS conditionally configures HTTP/2 on
@@ -3269,24 +3269,6 @@ func (tw *timeoutWriter) writeHeader(code int) {
        tw.code = code
 }
 
-// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
-// connections. It's used by ListenAndServe and ListenAndServeTLS so
-// dead TCP connections (e.g. closing laptop mid-download) eventually
-// go away.
-type tcpKeepAliveListener struct {
-       *net.TCPListener
-}
-
-func (ln tcpKeepAliveListener) Accept() (net.Conn, error) {
-       tc, err := ln.AcceptTCP()
-       if err != nil {
-               return nil, err
-       }
-       tc.SetKeepAlive(true)
-       tc.SetKeepAlivePeriod(3 * time.Minute)
-       return tc, nil
-}
-
 // onceCloseListener wraps a net.Listener, protecting it from
 // multiple Close calls.
 type onceCloseListener struct {
index db5d1f8482efe9e54dff3e65ae142d6350a46ec4..666c804169d1e10a4aee37610fbb030179fbfd08 100644 (file)
@@ -224,6 +224,7 @@ func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPConn, error) {
 // use variables of type Listener instead of assuming TCP.
 type TCPListener struct {
        fd *netFD
+       lc ListenConfig
 }
 
 // SyscallConn returns a raw network connection.
index f70ef6f43abb90707185d62a43c0b0688c3b35b6..e538f558653dd720d930ce3326e022c0f67c0dfa 100644 (file)
@@ -8,6 +8,7 @@ import (
        "context"
        "io"
        "os"
+       "time"
 )
 
 func (c *TCPConn) readFrom(r io.Reader) (int64, error) {
@@ -44,7 +45,16 @@ func (ln *TCPListener) accept() (*TCPConn, error) {
        if err != nil {
                return nil, err
        }
-       return newTCPConn(fd), nil
+       tc := newTCPConn(fd)
+       if ln.lc.KeepAlive >= 0 {
+               setKeepAlive(fd, true)
+               ka := ln.lc.KeepAlive
+               if ln.lc.KeepAlive == 0 {
+                       ka = 3 * time.Minute
+               }
+               setKeepAlivePeriod(fd, ka)
+       }
+       return tc, nil
 }
 
 func (ln *TCPListener) close() error {
@@ -74,5 +84,5 @@ func (sl *sysListener) listenTCP(ctx context.Context, laddr *TCPAddr) (*TCPListe
        if err != nil {
                return nil, err
        }
-       return &TCPListener{fd}, nil
+       return &TCPListener{fd: fd, lc: sl.ListenConfig}, nil
 }
index 64e71bf97c3cbea817c2b33ed71b5f3ff6a43d71..14d383b74d2632984c215b081c3f9a9340bbfa4c 100644 (file)
@@ -11,6 +11,7 @@ import (
        "io"
        "os"
        "syscall"
+       "time"
 )
 
 func sockaddrToTCP(sa syscall.Sockaddr) Addr {
@@ -140,7 +141,16 @@ func (ln *TCPListener) accept() (*TCPConn, error) {
        if err != nil {
                return nil, err
        }
-       return newTCPConn(fd), nil
+       tc := newTCPConn(fd)
+       if ln.lc.KeepAlive >= 0 {
+               setKeepAlive(fd, true)
+               ka := ln.lc.KeepAlive
+               if ln.lc.KeepAlive == 0 {
+                       ka = 3 * time.Minute
+               }
+               setKeepAlivePeriod(fd, ka)
+       }
+       return tc, nil
 }
 
 func (ln *TCPListener) close() error {
@@ -160,5 +170,5 @@ func (sl *sysListener) listenTCP(ctx context.Context, laddr *TCPAddr) (*TCPListe
        if err != nil {
                return nil, err
        }
-       return &TCPListener{fd}, nil
+       return &TCPListener{fd: fd, lc: sl.ListenConfig}, nil
 }