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  }