github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/listener/listener.go (about) 1 package listener 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 "time" 8 ) 9 10 // tcpKeepAliveListener sets TCP keep-alive timeouts on accepted 11 // connections. It's used by ListenAndServe and ListenAndServeTLS so 12 // dead TCP connections (e.g. closing laptop mid-download) eventually 13 // go away. 14 // it is a plain copy-paste from net/http/server.go 15 type tcpKeepAliveListener struct { 16 *net.TCPListener 17 } 18 19 func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { 20 tc, err := ln.AcceptTCP() 21 if err != nil { 22 return 23 } 24 tc.SetKeepAlive(true) 25 tc.SetKeepAlivePeriod(3 * time.Minute) 26 return tc, nil 27 } 28 29 // NewListener announces on laddr and net. Accepted values of the net are 30 // 'unix' and 'tcp' 31 func NewListener(net, laddr string) (net.Listener, error) { 32 switch net { 33 case "unix": 34 return newUnixListener(laddr) 35 case "tcp", "": // an empty net means tcp 36 return newTCPListener(laddr) 37 default: 38 return nil, fmt.Errorf("unknown address type %s", net) 39 } 40 } 41 42 func newUnixListener(laddr string) (net.Listener, error) { 43 fi, err := os.Stat(laddr) 44 if err == nil { 45 // the file exists. 46 // try to remove it if it's a socket 47 if !isSocket(fi.Mode()) { 48 return nil, fmt.Errorf("file %s exists and is not a socket", laddr) 49 } 50 51 if err := os.Remove(laddr); err != nil { 52 return nil, err 53 } 54 } else if !os.IsNotExist(err) { 55 // we can't do stat on the file. 56 // it means we can not remove it 57 return nil, err 58 } 59 60 return net.Listen("unix", laddr) 61 } 62 63 func isSocket(m os.FileMode) bool { 64 return m&os.ModeSocket != 0 65 } 66 67 func newTCPListener(laddr string) (net.Listener, error) { 68 ln, err := net.Listen("tcp", laddr) 69 if err != nil { 70 return nil, err 71 } 72 73 return tcpKeepAliveListener{ln.(*net.TCPListener)}, nil 74 }