1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2025-02-20 23:47:21 -05:00

refine dyn port

This commit is contained in:
Darien Raymond 2017-01-30 21:35:34 +01:00
parent f7f935a3c4
commit e7aa920c27
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169

View File

@ -12,27 +12,16 @@ import (
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
) )
type workerWithContext struct {
ctx context.Context
cancel context.CancelFunc
worker worker
}
func (w *workerWithContext) Close() {
w.cancel()
w.worker.Close()
}
type DynamicInboundHandler struct { type DynamicInboundHandler struct {
sync.Mutex
tag string tag string
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
proxyConfig interface{} proxyConfig interface{}
receiverConfig *proxyman.ReceiverConfig receiverConfig *proxyman.ReceiverConfig
portMutex sync.Mutex
portsInUse map[v2net.Port]bool portsInUse map[v2net.Port]bool
worker []*workerWithContext workerMutex sync.RWMutex
worker2Recycle []*workerWithContext worker []worker
lastRefresh time.Time lastRefresh time.Time
} }
@ -53,8 +42,9 @@ func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *p
func (h *DynamicInboundHandler) allocatePort() v2net.Port { func (h *DynamicInboundHandler) allocatePort() v2net.Port {
from := int(h.receiverConfig.PortRange.From) from := int(h.receiverConfig.PortRange.From)
delta := int(h.receiverConfig.PortRange.To) - from + 1 delta := int(h.receiverConfig.PortRange.To) - from + 1
h.Lock()
defer h.Unlock() h.portMutex.Lock()
defer h.portMutex.Unlock()
for { for {
r := dice.Roll(delta) r := dice.Roll(delta)
@ -67,30 +57,34 @@ func (h *DynamicInboundHandler) allocatePort() v2net.Port {
} }
} }
func (h *DynamicInboundHandler) refresh() error { func (h *DynamicInboundHandler) waitAnyCloseWorkers(ctx context.Context, cancel context.CancelFunc, workers []worker, duration time.Duration) {
h.lastRefresh = time.Now() time.Sleep(duration)
cancel()
ports2Del := make([]v2net.Port, 0, 16) ports2Del := make([]v2net.Port, len(workers))
for _, worker := range h.worker2Recycle { for idx, worker := range workers {
ports2Del[idx] = worker.Port()
worker.Close() worker.Close()
ports2Del = append(ports2Del, worker.worker.Port())
} }
h.Lock() h.portMutex.Lock()
for _, port := range ports2Del { for _, port := range ports2Del {
delete(h.portsInUse, port) delete(h.portsInUse, port)
} }
h.Unlock() h.portMutex.Unlock()
}
h.worker2Recycle, h.worker = h.worker, h.worker2Recycle[:0] func (h *DynamicInboundHandler) refresh() error {
h.lastRefresh = time.Now()
timeout := time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue())
ctx, cancel := context.WithTimeout(h.ctx, timeout)
workers := make([]worker, 0, h.receiverConfig.AllocationStrategy.GetConcurrencyValue())
address := h.receiverConfig.Listen.AsAddress() address := h.receiverConfig.Listen.AsAddress()
if address == nil { if address == nil {
address = v2net.AnyIP address = v2net.AnyIP
} }
for i := uint32(0); i < h.receiverConfig.AllocationStrategy.GetConcurrencyValue(); i++ { for i := uint32(0); i < h.receiverConfig.AllocationStrategy.GetConcurrencyValue(); i++ {
ctx, cancel := context.WithCancel(h.ctx)
port := h.allocatePort() port := h.allocatePort()
p, err := proxy.CreateInboundHandler(ctx, h.proxyConfig) p, err := proxy.CreateInboundHandler(ctx, h.proxyConfig)
if err != nil { if err != nil {
@ -109,13 +103,10 @@ func (h *DynamicInboundHandler) refresh() error {
allowPassiveConn: h.receiverConfig.AllowPassiveConnection, allowPassiveConn: h.receiverConfig.AllowPassiveConnection,
} }
if err := worker.Start(); err != nil { if err := worker.Start(); err != nil {
return err log.Warning("Proxyman:InboundHandler: Failed to create TCP worker: ", err)
continue
} }
h.worker = append(h.worker, &workerWithContext{ workers = append(workers, worker)
ctx: ctx,
cancel: cancel,
worker: worker,
})
} }
if nl.HasNetwork(v2net.Network_UDP) { if nl.HasNetwork(v2net.Network_UDP) {
@ -127,16 +118,19 @@ func (h *DynamicInboundHandler) refresh() error {
recvOrigDest: h.receiverConfig.ReceiveOriginalDestination, recvOrigDest: h.receiverConfig.ReceiveOriginalDestination,
} }
if err := worker.Start(); err != nil { if err := worker.Start(); err != nil {
return err log.Warning("Proxyman:InboundHandler: Failed to create UDP worker: ", err)
continue
} }
h.worker = append(h.worker, &workerWithContext{ workers = append(workers, worker)
ctx: ctx,
cancel: cancel,
worker: worker,
})
} }
} }
h.workerMutex.Lock()
h.worker = workers
h.workerMutex.Unlock()
go h.waitAnyCloseWorkers(ctx, cancel, workers, timeout)
return nil return nil
} }
@ -162,7 +156,10 @@ func (h *DynamicInboundHandler) Close() {
} }
func (h *DynamicInboundHandler) GetRandomInboundProxy() (proxy.Inbound, v2net.Port, int) { func (h *DynamicInboundHandler) GetRandomInboundProxy() (proxy.Inbound, v2net.Port, int) {
h.workerMutex.RLock()
defer h.workerMutex.RUnlock()
w := h.worker[dice.Roll(len(h.worker))] w := h.worker[dice.Roll(len(h.worker))]
expire := h.receiverConfig.AllocationStrategy.GetRefreshValue() - uint32(time.Since(h.lastRefresh)/time.Minute) expire := h.receiverConfig.AllocationStrategy.GetRefreshValue() - uint32(time.Since(h.lastRefresh)/time.Minute)
return w.worker.Proxy(), w.worker.Port(), int(expire) return w.Proxy(), w.Port(), int(expire)
} }