-
Notifications
You must be signed in to change notification settings - Fork 0
/
connection.go
181 lines (157 loc) · 3.68 KB
/
connection.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package internal
import (
"io"
"net"
"sync"
"time"
v2net "v2ray.com/core/common/net"
)
// ConnectionID is the ID of a connection.
type ConnectionID struct {
Local v2net.Address
Remote v2net.Address
RemotePort v2net.Port
}
// NewConnectionID creates a new ConnectionId.
func NewConnectionID(source v2net.Address, dest v2net.Destination) ConnectionID {
return ConnectionID{
Local: source,
Remote: dest.Address,
RemotePort: dest.Port,
}
}
// Reuser determines whether a connection can be reused or not.
type Reuser struct {
// userEnabled indicates connection-reuse enabled by user.
userEnabled bool
// appEnabled indicates connection-reuse enabled by app.
appEnabled bool
}
// ReuseConnection returns a tracker for tracking connection reusability.
func ReuseConnection(reuse bool) *Reuser {
return &Reuser{
userEnabled: reuse,
appEnabled: reuse,
}
}
// Connection is an implementation of net.Conn with re-usability.
type Connection struct {
sync.RWMutex
id ConnectionID
conn net.Conn
listener ConnectionRecyler
reuser *Reuser
}
// NewConnection creates a new connection.
func NewConnection(id ConnectionID, conn net.Conn, manager ConnectionRecyler, reuser *Reuser) *Connection {
return &Connection{
id: id,
conn: conn,
listener: manager,
reuser: reuser,
}
}
// Read implements net.Conn.Read().
func (v *Connection) Read(b []byte) (int, error) {
conn := v.underlyingConn()
if conn == nil {
return 0, io.EOF
}
return conn.Read(b)
}
// Write implement net.Conn.Write().
func (v *Connection) Write(b []byte) (int, error) {
conn := v.underlyingConn()
if conn == nil {
return 0, io.ErrClosedPipe
}
return conn.Write(b)
}
// Close implements net.Conn.Close(). If the connection is reusable, the underlying connection will be recycled.
func (v *Connection) Close() error {
if v == nil {
return io.ErrClosedPipe
}
v.Lock()
defer v.Unlock()
if v.conn == nil {
return io.ErrClosedPipe
}
if v.Reusable() {
v.listener.Put(v.id, v.conn)
return nil
}
err := v.conn.Close()
v.conn = nil
return err
}
// LocalAddr implements net.Conn.LocalAddr().
func (v *Connection) LocalAddr() net.Addr {
conn := v.underlyingConn()
if conn == nil {
return nil
}
return conn.LocalAddr()
}
// RemoteAddr implements net.Conn.RemoteAddr().
func (v *Connection) RemoteAddr() net.Addr {
conn := v.underlyingConn()
if conn == nil {
return nil
}
return conn.RemoteAddr()
}
// SetDeadline implements net.Conn.SetDeadline().
func (v *Connection) SetDeadline(t time.Time) error {
conn := v.underlyingConn()
if conn == nil {
return nil
}
return conn.SetDeadline(t)
}
// SetReadDeadline implements net.Conn.SetReadDeadline().
func (v *Connection) SetReadDeadline(t time.Time) error {
conn := v.underlyingConn()
if conn == nil {
return nil
}
return conn.SetReadDeadline(t)
}
// SetWriteDeadline implements net.Conn.SetWriteDeadline().
func (v *Connection) SetWriteDeadline(t time.Time) error {
conn := v.underlyingConn()
if conn == nil {
return nil
}
return conn.SetWriteDeadline(t)
}
// SetReusable implements internet.Reusable.SetReusable().
func (v *Connection) SetReusable(reusable bool) {
if v == nil {
return
}
v.reuser.appEnabled = reusable
}
// Reusable implements internet.Reusable.Reusable().
func (v *Connection) Reusable() bool {
if v == nil {
return false
}
return v.reuser.userEnabled && v.reuser.appEnabled
}
// SysFd implement internet.SysFd.SysFd().
func (v *Connection) SysFd() (int, error) {
conn := v.underlyingConn()
if conn == nil {
return 0, io.ErrClosedPipe
}
return GetSysFd(conn)
}
func (v *Connection) underlyingConn() net.Conn {
if v == nil {
return nil
}
v.RLock()
defer v.RUnlock()
return v.conn
}