blob: 4ff8e7f0010ca66a992a9e67f368b8b830bc745a [file] [log] [blame]
khenaidoo59ce9dd2019-11-11 13:05:32 -05001// 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
15package transport
16
17import (
18 "crypto/tls"
19 "fmt"
20 "net"
21 "time"
22)
23
24type 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
33func 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
46type keepaliveListener struct{ net.Listener }
47
48func (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.
63type 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.
70func (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.
89func newTLSKeepaliveListener(inner net.Listener, config *tls.Config) net.Listener {
90 l := &tlsKeepaliveListener{}
91 l.Listener = inner
92 l.config = config
93 return l
94}