2016-05-13 06:48:53 +03:00
|
|
|
// Copyright 2015 The etcd Authors
|
2015-01-25 06:19:16 +03:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2015-01-06 23:09:34 +03:00
|
|
|
|
|
|
|
package transport
|
|
|
|
|
|
|
|
import (
|
2015-01-29 20:38:43 +03:00
|
|
|
"crypto/tls"
|
2015-07-14 22:18:15 +03:00
|
|
|
"fmt"
|
2015-01-06 23:09:34 +03:00
|
|
|
"net"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2016-01-08 21:10:05 +03:00
|
|
|
type keepAliveConn interface {
|
|
|
|
SetKeepAlive(bool) error
|
|
|
|
SetKeepAlivePeriod(d time.Duration) error
|
|
|
|
}
|
|
|
|
|
2015-01-06 23:09:34 +03:00
|
|
|
// NewKeepAliveListener returns a listener that listens on the given address.
|
2016-01-07 08:59:38 +03:00
|
|
|
// Be careful when wrap around KeepAliveListener with another Listener if TLSInfo is not nil.
|
|
|
|
// Some pkgs (like go/http) might expect Listener to return TLSConn type to start TLS handshake.
|
2015-01-06 23:09:34 +03:00
|
|
|
// http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
|
2016-03-22 07:01:21 +03:00
|
|
|
func NewKeepAliveListener(l net.Listener, scheme string, tlscfg *tls.Config) (net.Listener, error) {
|
2015-07-14 22:18:15 +03:00
|
|
|
if scheme == "https" {
|
2016-03-22 07:01:21 +03:00
|
|
|
if tlscfg == nil {
|
2016-01-07 08:59:38 +03:00
|
|
|
return nil, fmt.Errorf("cannot listen on TLS for given listener: KeyFile and CertFile are not presented")
|
2015-07-14 22:18:15 +03:00
|
|
|
}
|
2016-03-22 07:01:21 +03:00
|
|
|
return newTLSKeepaliveListener(l, tlscfg), nil
|
2015-01-29 20:38:43 +03:00
|
|
|
}
|
|
|
|
|
2015-01-06 23:09:34 +03:00
|
|
|
return &keepaliveListener{
|
2015-01-29 20:38:43 +03:00
|
|
|
Listener: l,
|
2015-01-06 23:09:34 +03:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2015-01-29 20:38:43 +03:00
|
|
|
type keepaliveListener struct{ net.Listener }
|
2015-01-06 23:09:34 +03:00
|
|
|
|
|
|
|
func (kln *keepaliveListener) Accept() (net.Conn, error) {
|
|
|
|
c, err := kln.Listener.Accept()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-01-08 21:10:05 +03:00
|
|
|
kac := c.(keepAliveConn)
|
2015-01-06 23:09:34 +03:00
|
|
|
// detection time: tcp_keepalive_time + tcp_keepalive_probes + tcp_keepalive_intvl
|
|
|
|
// default on linux: 30 + 8 * 30
|
|
|
|
// default on osx: 30 + 8 * 75
|
2016-01-08 21:10:05 +03:00
|
|
|
kac.SetKeepAlive(true)
|
|
|
|
kac.SetKeepAlivePeriod(30 * time.Second)
|
|
|
|
return c, nil
|
2015-01-06 23:09:34 +03:00
|
|
|
}
|
2015-01-29 20:38:43 +03:00
|
|
|
|
|
|
|
// A tlsKeepaliveListener implements a network listener (net.Listener) for TLS connections.
|
|
|
|
type tlsKeepaliveListener struct {
|
|
|
|
net.Listener
|
|
|
|
config *tls.Config
|
|
|
|
}
|
|
|
|
|
|
|
|
// Accept waits for and returns the next incoming TLS connection.
|
|
|
|
// The returned connection c is a *tls.Conn.
|
|
|
|
func (l *tlsKeepaliveListener) Accept() (c net.Conn, err error) {
|
|
|
|
c, err = l.Listener.Accept()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2016-01-08 21:10:05 +03:00
|
|
|
kac := c.(keepAliveConn)
|
2015-01-29 20:38:43 +03:00
|
|
|
// detection time: tcp_keepalive_time + tcp_keepalive_probes + tcp_keepalive_intvl
|
|
|
|
// default on linux: 30 + 8 * 30
|
|
|
|
// default on osx: 30 + 8 * 75
|
2016-01-08 21:10:05 +03:00
|
|
|
kac.SetKeepAlive(true)
|
|
|
|
kac.SetKeepAlivePeriod(30 * time.Second)
|
2015-01-29 20:38:43 +03:00
|
|
|
c = tls.Server(c, l.config)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewListener creates a Listener which accepts connections from an inner
|
|
|
|
// Listener and wraps each connection with Server.
|
|
|
|
// The configuration config must be non-nil and must have
|
|
|
|
// at least one certificate.
|
|
|
|
func newTLSKeepaliveListener(inner net.Listener, config *tls.Config) net.Listener {
|
|
|
|
l := &tlsKeepaliveListener{}
|
|
|
|
l.Listener = inner
|
|
|
|
l.config = config
|
|
|
|
return l
|
|
|
|
}
|