]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: use TCP keep-alives for ListenAndServe and ListenAndServeTLS
authorBrad Fitzpatrick <bradfitz@golang.org>
Thu, 9 Jan 2014 23:05:09 +0000 (15:05 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 9 Jan 2014 23:05:09 +0000 (15:05 -0800)
Our default behavior for the common cases shouldn't lead to
leaked TCP connections (e.g. from people closing laptops) when
their Go servers are exposed to the open Internet without a
proxy in front.

Too many users on golang-nuts have learned this the hard way.

No API change. Only ListenAndServe and ListenAndServeTLS are
updated.

R=golang-codereviews, cespare, gobot, rsc, minux.ma
CC=golang-codereviews
https://golang.org/cl/48300043

src/pkg/net/http/server.go

index 7ebd8575f3beb7d1640b14451e8c0cfb12fe2aa1..a56aa3df312a0f2743873c339a0ceebca8ab31c4 100644 (file)
@@ -1608,11 +1608,11 @@ func (srv *Server) ListenAndServe() error {
        if addr == "" {
                addr = ":http"
        }
-       l, e := net.Listen("tcp", addr)
-       if e != nil {
-               return e
+       ln, err := net.Listen("tcp", addr)
+       if err != nil {
+               return err
        }
-       return srv.Serve(l)
+       return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
 }
 
 // Serve accepts incoming connections on the Listener l, creating a
@@ -1742,12 +1742,12 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
                return err
        }
 
-       conn, err := net.Listen("tcp", addr)
+       ln, err := net.Listen("tcp", addr)
        if err != nil {
                return err
        }
 
-       tlsListener := tls.NewListener(conn, config)
+       tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
        return srv.Serve(tlsListener)
 }
 
@@ -1837,6 +1837,24 @@ func (tw *timeoutWriter) WriteHeader(code int) {
        tw.w.WriteHeader(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() (c net.Conn, err error) {
+       tc, err := ln.AcceptTCP()
+       if err != nil {
+               return
+       }
+       tc.SetKeepAlive(true)
+       tc.SetKeepAlivePeriod(3 * time.Minute)
+       return tc, nil
+}
+
 // globalOptionsHandler responds to "OPTIONS *" requests.
 type globalOptionsHandler struct{}