/
keepalive.go
67 lines (59 loc) · 1.83 KB
/
keepalive.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package httpu
import (
"crypto/tls"
"net"
"reflect"
"time"
"unsafe"
)
var (
// DefaultKeepAliveIdleInterval specifies how long connection can be idle
// before sending keepalive message.
DefaultKeepAliveIdleInterval = 15 * time.Minute
// DefaultKeepAliveCount specifies maximal number of keepalive messages
// sent before marking connection as dead.
DefaultKeepAliveCount = 8
// DefaultKeepAliveInterval specifies how often retry sending keepalive
// messages when no response is received.
DefaultKeepAliveInterval = 5 * time.Second
)
type KeepAliveListener struct {
net.Listener
// DefaultKeepAliveCount specifies maximal number of keepalive messages
// sent before marking connection as dead.
KeepAliveCount int
// DefaultKeepAliveIdleInterval specifies how long connection can be idle
// before sending keepalive message.
KeepAliveIdleInterval time.Duration
// DefaultKeepAliveInterval specifies how often retry sending keepalive
// messages when no response is received.
KeepAliveInterval time.Duration
}
func NewKeepAliveListener(listener net.Listener) *KeepAliveListener {
return &KeepAliveListener{
Listener: listener,
KeepAliveCount: DefaultKeepAliveCount,
KeepAliveIdleInterval: DefaultKeepAliveIdleInterval,
KeepAliveInterval: DefaultKeepAliveInterval,
}
}
func (ln KeepAliveListener) Accept() (net.Conn, error) {
c, err := ln.Listener.Accept()
if err != nil {
return nil, err
}
if tlsConn, ok := c.(*tls.Conn); ok {
var t time.Time
tlsConn.SetDeadline(t)
tlsConn.SetWriteDeadline(t)
v := reflect.ValueOf(tlsConn).Elem().FieldByName("conn")
ptrToY := unsafe.Pointer(v.UnsafeAddr())
realPtrToY := (*net.Conn)(ptrToY)
if err = ln.keepAlive(*(realPtrToY)); err != nil {
return nil, err
}
} else if err = ln.keepAlive(c); err != nil {
return nil, err
}
return c, nil
}