| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 | 
							- package tcp
 
- import (
 
- 	"net"
 
- 	"sync"
 
- 	"time"
 
- 	"v2ray.com/core/common/signal"
 
- )
 
- type AwaitingConnection struct {
 
- 	conn   net.Conn
 
- 	expire time.Time
 
- }
 
- func (this *AwaitingConnection) Expired() bool {
 
- 	return this.expire.Before(time.Now())
 
- }
 
- type ConnectionCache struct {
 
- 	sync.Mutex
 
- 	cache       map[string][]*AwaitingConnection
 
- 	cleanupOnce signal.Once
 
- }
 
- func NewConnectionCache() *ConnectionCache {
 
- 	return &ConnectionCache{
 
- 		cache: make(map[string][]*AwaitingConnection),
 
- 	}
 
- }
 
- func (this *ConnectionCache) Cleanup() {
 
- 	defer this.cleanupOnce.Reset()
 
- 	for len(this.cache) > 0 {
 
- 		time.Sleep(time.Second * 4)
 
- 		this.Lock()
 
- 		for key, value := range this.cache {
 
- 			size := len(value)
 
- 			changed := false
 
- 			for i := 0; i < size; {
 
- 				if value[i].Expired() {
 
- 					value[i].conn.Close()
 
- 					value[i] = value[size-1]
 
- 					size--
 
- 					changed = true
 
- 				} else {
 
- 					i++
 
- 				}
 
- 			}
 
- 			if changed {
 
- 				for i := size; i < len(value); i++ {
 
- 					value[i] = nil
 
- 				}
 
- 				value = value[:size]
 
- 				this.cache[key] = value
 
- 			}
 
- 		}
 
- 		this.Unlock()
 
- 	}
 
- }
 
- func (this *ConnectionCache) Recycle(dest string, conn net.Conn) {
 
- 	this.Lock()
 
- 	defer this.Unlock()
 
- 	aconn := &AwaitingConnection{
 
- 		conn:   conn,
 
- 		expire: time.Now().Add(time.Second * 4),
 
- 	}
 
- 	var list []*AwaitingConnection
 
- 	if v, found := this.cache[dest]; found {
 
- 		v = append(v, aconn)
 
- 		list = v
 
- 	} else {
 
- 		list = []*AwaitingConnection{aconn}
 
- 	}
 
- 	this.cache[dest] = list
 
- 	go this.cleanupOnce.Do(this.Cleanup)
 
- }
 
- func FindFirstValid(list []*AwaitingConnection) int {
 
- 	for idx, conn := range list {
 
- 		if !conn.Expired() {
 
- 			return idx
 
- 		}
 
- 		go conn.conn.Close()
 
- 	}
 
- 	return -1
 
- }
 
- func (this *ConnectionCache) Get(dest string) net.Conn {
 
- 	this.Lock()
 
- 	defer this.Unlock()
 
- 	list, found := this.cache[dest]
 
- 	if !found {
 
- 		return nil
 
- 	}
 
- 	firstValid := FindFirstValid(list)
 
- 	if firstValid == -1 {
 
- 		delete(this.cache, dest)
 
- 		return nil
 
- 	}
 
- 	res := list[firstValid].conn
 
- 	list = list[firstValid+1:]
 
- 	this.cache[dest] = list
 
- 	return res
 
- }
 
 
  |