|
|
@@ -9,50 +9,59 @@ import (
|
|
|
"v2ray.com/core/common/signal"
|
|
|
)
|
|
|
|
|
|
+// ConnectionRecyler is the interface for recycling connections.
|
|
|
type ConnectionRecyler interface {
|
|
|
- Put(ConnectionId, net.Conn)
|
|
|
+ // Put returns a connection back to a connection pool.
|
|
|
+ Put(ConnectionID, net.Conn)
|
|
|
}
|
|
|
|
|
|
-type ConnectionId struct {
|
|
|
+// ConnectionID is the ID of a connection.
|
|
|
+type ConnectionID struct {
|
|
|
Local v2net.Address
|
|
|
Remote v2net.Address
|
|
|
RemotePort v2net.Port
|
|
|
}
|
|
|
|
|
|
-func NewConnectionId(source v2net.Address, dest v2net.Destination) ConnectionId {
|
|
|
- return ConnectionId{
|
|
|
+// NewConnectionID creates a new ConnectionId.
|
|
|
+func NewConnectionID(source v2net.Address, dest v2net.Destination) ConnectionID {
|
|
|
+ return ConnectionID{
|
|
|
Local: source,
|
|
|
Remote: dest.Address,
|
|
|
RemotePort: dest.Port,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// ExpiringConnection is a connection that will expire in certain time.
|
|
|
type ExpiringConnection struct {
|
|
|
conn net.Conn
|
|
|
expire time.Time
|
|
|
}
|
|
|
|
|
|
-func (o *ExpiringConnection) Expired() bool {
|
|
|
- return o.expire.Before(time.Now())
|
|
|
+// Expired returns true if the connection has expired.
|
|
|
+func (ec *ExpiringConnection) Expired() bool {
|
|
|
+ return ec.expire.Before(time.Now())
|
|
|
}
|
|
|
|
|
|
+// Pool is a connection pool.
|
|
|
type Pool struct {
|
|
|
sync.Mutex
|
|
|
- connsByDest map[ConnectionId][]*ExpiringConnection
|
|
|
+ connsByDest map[ConnectionID][]*ExpiringConnection
|
|
|
cleanupOnce signal.Once
|
|
|
}
|
|
|
|
|
|
+// NewConnectionPool creates a new Pool.
|
|
|
func NewConnectionPool() *Pool {
|
|
|
return &Pool{
|
|
|
- connsByDest: make(map[ConnectionId][]*ExpiringConnection),
|
|
|
+ connsByDest: make(map[ConnectionID][]*ExpiringConnection),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (o *Pool) Get(id ConnectionId) net.Conn {
|
|
|
- o.Lock()
|
|
|
- defer o.Unlock()
|
|
|
+// Get returns a connection with matching connection ID. Nil if not found.
|
|
|
+func (p *Pool) Get(id ConnectionID) net.Conn {
|
|
|
+ p.Lock()
|
|
|
+ defer p.Unlock()
|
|
|
|
|
|
- list, found := o.connsByDest[id]
|
|
|
+ list, found := p.connsByDest[id]
|
|
|
if !found {
|
|
|
return nil
|
|
|
}
|
|
|
@@ -72,18 +81,18 @@ func (o *Pool) Get(id ConnectionId) net.Conn {
|
|
|
list[connIdx] = list[listLen-1]
|
|
|
}
|
|
|
list = list[:listLen-1]
|
|
|
- o.connsByDest[id] = list
|
|
|
+ p.connsByDest[id] = list
|
|
|
return conn.conn
|
|
|
}
|
|
|
|
|
|
-func (o *Pool) Cleanup() {
|
|
|
- defer o.cleanupOnce.Reset()
|
|
|
+func (p *Pool) cleanup() {
|
|
|
+ defer p.cleanupOnce.Reset()
|
|
|
|
|
|
- for len(o.connsByDest) > 0 {
|
|
|
+ for len(p.connsByDest) > 0 {
|
|
|
time.Sleep(time.Second * 5)
|
|
|
expiredConns := make([]net.Conn, 0, 16)
|
|
|
- o.Lock()
|
|
|
- for dest, list := range o.connsByDest {
|
|
|
+ p.Lock()
|
|
|
+ for dest, list := range p.connsByDest {
|
|
|
validConns := make([]*ExpiringConnection, 0, len(list))
|
|
|
for _, conn := range list {
|
|
|
if conn.Expired() {
|
|
|
@@ -93,34 +102,35 @@ func (o *Pool) Cleanup() {
|
|
|
}
|
|
|
}
|
|
|
if len(validConns) != len(list) {
|
|
|
- o.connsByDest[dest] = validConns
|
|
|
+ p.connsByDest[dest] = validConns
|
|
|
}
|
|
|
}
|
|
|
- o.Unlock()
|
|
|
+ p.Unlock()
|
|
|
for _, conn := range expiredConns {
|
|
|
conn.Close()
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (o *Pool) Put(id ConnectionId, conn net.Conn) {
|
|
|
+// Put implements ConnectionRecyler.Put().
|
|
|
+func (p *Pool) Put(id ConnectionID, conn net.Conn) {
|
|
|
expiringConn := &ExpiringConnection{
|
|
|
conn: conn,
|
|
|
expire: time.Now().Add(time.Second * 4),
|
|
|
}
|
|
|
|
|
|
- o.Lock()
|
|
|
- defer o.Unlock()
|
|
|
+ p.Lock()
|
|
|
+ defer p.Unlock()
|
|
|
|
|
|
- list, found := o.connsByDest[id]
|
|
|
+ list, found := p.connsByDest[id]
|
|
|
if !found {
|
|
|
list = []*ExpiringConnection{expiringConn}
|
|
|
} else {
|
|
|
list = append(list, expiringConn)
|
|
|
}
|
|
|
- o.connsByDest[id] = list
|
|
|
+ p.connsByDest[id] = list
|
|
|
|
|
|
- o.cleanupOnce.Do(func() {
|
|
|
- go o.Cleanup()
|
|
|
+ p.cleanupOnce.Do(func() {
|
|
|
+ go p.cleanup()
|
|
|
})
|
|
|
}
|