1
0
mirror of https://github.com/golang/go synced 2024-11-27 00:01:23 -07:00

net: add KeepAlive with default to ListenConfig

This commit adds a KeepAlive field to ListenConfig and uses it
analogously to Dialer.KeepAlive to set TCP KeepAlives per default on
Accept()
This commit is contained in:
Leo Antunes 2019-04-03 23:01:16 +02:00
parent b0bcd7aeb0
commit e9e035d53e
7 changed files with 37 additions and 26 deletions

View 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.

View 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) {

View 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
}

View 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 {

View 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.

View 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
}

View 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
}