forked from tus/tusd
/
listener.go
100 lines (83 loc) · 2.09 KB
/
listener.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package cli
import (
"net"
"time"
)
// Listener wraps a net.Listener, and gives a place to store the timeout
// parameters. On Accept, it will wrap the net.Conn with our own Conn for us.
// Original implementation taken from https://gist.github.com/jbardin/9663312
// Thanks! <3
type Listener struct {
net.Listener
ReadTimeout time.Duration
WriteTimeout time.Duration
}
func (l *Listener) Accept() (net.Conn, error) {
c, err := l.Listener.Accept()
if err != nil {
return nil, err
}
go MetricsOpenConnections.Inc()
tc := &Conn{
Conn: c,
ReadTimeout: l.ReadTimeout,
WriteTimeout: l.WriteTimeout,
}
return tc, nil
}
// Conn wraps a net.Conn, and sets a deadline for every read
// and write operation.
type Conn struct {
net.Conn
ReadTimeout time.Duration
WriteTimeout time.Duration
// closeRecorded will be true if the connection has been closed and the
// corresponding prometheus counter has been decremented. It will be used to
// avoid duplicated modifications to this metric.
closeRecorded bool
}
func (c *Conn) Read(b []byte) (int, error) {
var err error
if c.ReadTimeout > 0 {
err = c.Conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
} else {
err = c.Conn.SetReadDeadline(time.Time{})
}
if err != nil {
return 0, err
}
return c.Conn.Read(b)
}
func (c *Conn) Write(b []byte) (int, error) {
var err error
if c.WriteTimeout > 0 {
err = c.Conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
} else {
err = c.Conn.SetWriteDeadline(time.Time{})
}
if err != nil {
return 0, err
}
return c.Conn.Write(b)
}
func (c *Conn) Close() error {
// Only decremented the prometheus counter if the Close function has not been
// invoked before to avoid duplicated modifications.
if !c.closeRecorded {
c.closeRecorded = true
MetricsOpenConnections.Dec()
}
return c.Conn.Close()
}
func NewListener(addr string, readTimeout, writeTimeout time.Duration) (net.Listener, error) {
l, err := net.Listen("tcp", addr)
if err != nil {
return nil, err
}
tl := &Listener{
Listener: l,
ReadTimeout: readTimeout,
WriteTimeout: writeTimeout,
}
return tl, nil
}