go.etcd.io/etcd@v3.3.27+incompatible/pkg/transport/keepalive_listener.go (about) 1 // Copyright 2015 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package transport 16 17 import ( 18 "crypto/tls" 19 "fmt" 20 "net" 21 "time" 22 ) 23 24 type keepAliveConn interface { 25 SetKeepAlive(bool) error 26 SetKeepAlivePeriod(d time.Duration) error 27 } 28 29 // NewKeepAliveListener returns a listener that listens on the given address. 30 // Be careful when wrap around KeepAliveListener with another Listener if TLSInfo is not nil. 31 // Some pkgs (like go/http) might expect Listener to return TLSConn type to start TLS handshake. 32 // http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html 33 func NewKeepAliveListener(l net.Listener, scheme string, tlscfg *tls.Config) (net.Listener, error) { 34 if scheme == "https" { 35 if tlscfg == nil { 36 return nil, fmt.Errorf("cannot listen on TLS for given listener: KeyFile and CertFile are not presented") 37 } 38 return newTLSKeepaliveListener(l, tlscfg), nil 39 } 40 41 return &keepaliveListener{ 42 Listener: l, 43 }, nil 44 } 45 46 type keepaliveListener struct{ net.Listener } 47 48 func (kln *keepaliveListener) Accept() (net.Conn, error) { 49 c, err := kln.Listener.Accept() 50 if err != nil { 51 return nil, err 52 } 53 kac := c.(keepAliveConn) 54 // detection time: tcp_keepalive_time + tcp_keepalive_probes + tcp_keepalive_intvl 55 // default on linux: 30 + 8 * 30 56 // default on osx: 30 + 8 * 75 57 kac.SetKeepAlive(true) 58 kac.SetKeepAlivePeriod(30 * time.Second) 59 return c, nil 60 } 61 62 // A tlsKeepaliveListener implements a network listener (net.Listener) for TLS connections. 63 type tlsKeepaliveListener struct { 64 net.Listener 65 config *tls.Config 66 } 67 68 // Accept waits for and returns the next incoming TLS connection. 69 // The returned connection c is a *tls.Conn. 70 func (l *tlsKeepaliveListener) Accept() (c net.Conn, err error) { 71 c, err = l.Listener.Accept() 72 if err != nil { 73 return 74 } 75 kac := c.(keepAliveConn) 76 // detection time: tcp_keepalive_time + tcp_keepalive_probes + tcp_keepalive_intvl 77 // default on linux: 30 + 8 * 30 78 // default on osx: 30 + 8 * 75 79 kac.SetKeepAlive(true) 80 kac.SetKeepAlivePeriod(30 * time.Second) 81 c = tls.Server(c, l.config) 82 return c, nil 83 } 84 85 // NewListener creates a Listener which accepts connections from an inner 86 // Listener and wraps each connection with Server. 87 // The configuration config must be non-nil and must have 88 // at least one certificate. 89 func newTLSKeepaliveListener(inner net.Listener, config *tls.Config) net.Listener { 90 l := &tlsKeepaliveListener{} 91 l.Listener = inner 92 l.config = config 93 return l 94 }