mirror of https://github.com/v2ray/v2ray-core
remove context in struct
parent
a1ae4aa515
commit
efcb567273
|
@ -72,7 +72,7 @@ func (c *Commander) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commander) Close() {
|
func (c *Commander) Close() error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
|
|
||||||
|
@ -80,6 +80,8 @@ func (c *Commander) Close() {
|
||||||
c.server.Stop()
|
c.server.Stop()
|
||||||
c.server = nil
|
c.server = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package commander
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"v2ray.com/core/common/signal"
|
"v2ray.com/core/common/signal"
|
||||||
"v2ray.com/core/transport/ray"
|
"v2ray.com/core/transport/ray"
|
||||||
|
@ -43,12 +44,24 @@ func (l *OutboundListener) Addr() net.Addr {
|
||||||
type CommanderOutbound struct {
|
type CommanderOutbound struct {
|
||||||
tag string
|
tag string
|
||||||
listener *OutboundListener
|
listener *OutboundListener
|
||||||
|
access sync.RWMutex
|
||||||
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *CommanderOutbound) Dispatch(ctx context.Context, r ray.OutboundRay) {
|
func (co *CommanderOutbound) Dispatch(ctx context.Context, r ray.OutboundRay) {
|
||||||
|
co.access.RLock()
|
||||||
|
|
||||||
|
if co.closed {
|
||||||
|
r.OutboundInput().CloseError()
|
||||||
|
r.OutboundOutput().CloseError()
|
||||||
|
co.access.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
closeSignal := signal.NewNotifier()
|
closeSignal := signal.NewNotifier()
|
||||||
c := ray.NewConnection(r.OutboundInput(), r.OutboundOutput(), ray.ConnCloseSignal(closeSignal))
|
c := ray.NewConnection(r.OutboundInput(), r.OutboundOutput(), ray.ConnCloseSignal(closeSignal))
|
||||||
co.listener.add(c)
|
co.listener.add(c)
|
||||||
|
co.access.RUnlock()
|
||||||
<-closeSignal.Wait()
|
<-closeSignal.Wait()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -59,7 +72,17 @@ func (co *CommanderOutbound) Tag() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *CommanderOutbound) Start() error {
|
func (co *CommanderOutbound) Start() error {
|
||||||
|
co.access.Lock()
|
||||||
|
co.closed = false
|
||||||
|
co.access.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *CommanderOutbound) Close() {}
|
func (co *CommanderOutbound) Close() error {
|
||||||
|
co.access.Lock()
|
||||||
|
co.closed = true
|
||||||
|
co.listener.Close()
|
||||||
|
co.access.Unlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ func (*DefaultDispatcher) Start() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close implements app.Application.
|
// Close implements app.Application.
|
||||||
func (*DefaultDispatcher) Close() {}
|
func (*DefaultDispatcher) Close() error { return nil }
|
||||||
|
|
||||||
// Dispatch implements core.Dispatcher.
|
// Dispatch implements core.Dispatcher.
|
||||||
func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destination) (ray.InboundRay, error) {
|
func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destination) (ray.InboundRay, error) {
|
||||||
|
|
|
@ -83,7 +83,8 @@ func (s *Server) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Server) Close() {
|
func (*Server) Close() error {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetCached(domain string) []net.IP {
|
func (s *Server) GetCached(domain string) []net.IP {
|
||||||
|
|
|
@ -103,11 +103,13 @@ func (g *Instance) Handle(msg log.Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close implement app.Application.Close().
|
// Close implement app.Application.Close().
|
||||||
func (g *Instance) Close() {
|
func (g *Instance) Close() error {
|
||||||
g.Lock()
|
g.Lock()
|
||||||
defer g.Unlock()
|
defer g.Unlock()
|
||||||
|
|
||||||
g.active = false
|
g.active = false
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -51,7 +51,8 @@ func (m *Instance) Start() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close implements app.Application.Close().
|
// Close implements app.Application.Close().
|
||||||
func (m *Instance) Close() {
|
func (m *Instance) Close() error {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -119,7 +119,9 @@ func (*feature) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*feature) Close() {}
|
func (*feature) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
|
||||||
|
|
|
@ -76,10 +76,11 @@ func (h *AlwaysOnInboundHandler) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *AlwaysOnInboundHandler) Close() {
|
func (h *AlwaysOnInboundHandler) Close() error {
|
||||||
for _, worker := range h.workers {
|
for _, worker := range h.workers {
|
||||||
worker.Close()
|
worker.Close()
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *AlwaysOnInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) {
|
func (h *AlwaysOnInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) {
|
||||||
|
|
|
@ -5,17 +5,18 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/app/proxyman"
|
"v2ray.com/core/app/proxyman"
|
||||||
"v2ray.com/core/app/proxyman/mux"
|
"v2ray.com/core/app/proxyman/mux"
|
||||||
"v2ray.com/core/common/dice"
|
"v2ray.com/core/common/dice"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
|
"v2ray.com/core/common/signal"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DynamicInboundHandler struct {
|
type DynamicInboundHandler struct {
|
||||||
tag string
|
tag string
|
||||||
ctx context.Context
|
v *core.Instance
|
||||||
cancel context.CancelFunc
|
|
||||||
proxyConfig interface{}
|
proxyConfig interface{}
|
||||||
receiverConfig *proxyman.ReceiverConfig
|
receiverConfig *proxyman.ReceiverConfig
|
||||||
portMutex sync.Mutex
|
portMutex sync.Mutex
|
||||||
|
@ -24,18 +25,26 @@ type DynamicInboundHandler struct {
|
||||||
worker []worker
|
worker []worker
|
||||||
lastRefresh time.Time
|
lastRefresh time.Time
|
||||||
mux *mux.Server
|
mux *mux.Server
|
||||||
|
task *signal.PeriodicTask
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*DynamicInboundHandler, error) {
|
func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*DynamicInboundHandler, error) {
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
v := core.FromContext(ctx)
|
||||||
|
if v == nil {
|
||||||
|
return nil, newError("V is not in context.")
|
||||||
|
}
|
||||||
h := &DynamicInboundHandler{
|
h := &DynamicInboundHandler{
|
||||||
ctx: ctx,
|
|
||||||
tag: tag,
|
tag: tag,
|
||||||
cancel: cancel,
|
|
||||||
proxyConfig: proxyConfig,
|
proxyConfig: proxyConfig,
|
||||||
receiverConfig: receiverConfig,
|
receiverConfig: receiverConfig,
|
||||||
portsInUse: make(map[net.Port]bool),
|
portsInUse: make(map[net.Port]bool),
|
||||||
mux: mux.NewServer(ctx),
|
mux: mux.NewServer(ctx),
|
||||||
|
v: v,
|
||||||
|
}
|
||||||
|
|
||||||
|
h.task = &signal.PeriodicTask{
|
||||||
|
Interval: time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()),
|
||||||
|
Execute: h.refresh,
|
||||||
}
|
}
|
||||||
|
|
||||||
return h, nil
|
return h, nil
|
||||||
|
@ -59,9 +68,7 @@ func (h *DynamicInboundHandler) allocatePort() net.Port {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) waitAnyCloseWorkers(ctx context.Context, cancel context.CancelFunc, workers []worker, duration time.Duration) {
|
func (h *DynamicInboundHandler) closeWorkers(workers []worker) {
|
||||||
time.Sleep(duration)
|
|
||||||
cancel()
|
|
||||||
ports2Del := make([]net.Port, len(workers))
|
ports2Del := make([]net.Port, len(workers))
|
||||||
for idx, worker := range workers {
|
for idx, worker := range workers {
|
||||||
ports2Del[idx] = worker.Port()
|
ports2Del[idx] = worker.Port()
|
||||||
|
@ -80,7 +87,6 @@ func (h *DynamicInboundHandler) refresh() error {
|
||||||
|
|
||||||
timeout := time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()) * 2
|
timeout := time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()) * 2
|
||||||
concurrency := h.receiverConfig.AllocationStrategy.GetConcurrencyValue()
|
concurrency := h.receiverConfig.AllocationStrategy.GetConcurrencyValue()
|
||||||
ctx, cancel := context.WithTimeout(h.ctx, timeout)
|
|
||||||
workers := make([]worker, 0, concurrency)
|
workers := make([]worker, 0, concurrency)
|
||||||
|
|
||||||
address := h.receiverConfig.Listen.AsAddress()
|
address := h.receiverConfig.Listen.AsAddress()
|
||||||
|
@ -89,11 +95,12 @@ func (h *DynamicInboundHandler) refresh() error {
|
||||||
}
|
}
|
||||||
for i := uint32(0); i < concurrency; i++ {
|
for i := uint32(0); i < concurrency; i++ {
|
||||||
port := h.allocatePort()
|
port := h.allocatePort()
|
||||||
p, err := proxy.CreateInboundHandler(ctx, h.proxyConfig)
|
rawProxy, err := h.v.CreateObject(h.proxyConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newError("failed to create proxy instance").Base(err).AtWarning().WriteToLog()
|
newError("failed to create proxy instance").Base(err).AtWarning().WriteToLog()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
p := rawProxy.(proxy.Inbound)
|
||||||
nl := p.Network()
|
nl := p.Network()
|
||||||
if nl.HasNetwork(net.Network_TCP) {
|
if nl.HasNetwork(net.Network_TCP) {
|
||||||
worker := &tcpWorker{
|
worker := &tcpWorker{
|
||||||
|
@ -134,33 +141,19 @@ func (h *DynamicInboundHandler) refresh() error {
|
||||||
h.worker = workers
|
h.worker = workers
|
||||||
h.workerMutex.Unlock()
|
h.workerMutex.Unlock()
|
||||||
|
|
||||||
go h.waitAnyCloseWorkers(ctx, cancel, workers, timeout)
|
time.AfterFunc(timeout, func() {
|
||||||
|
h.closeWorkers(workers)
|
||||||
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) monitor() {
|
|
||||||
timer := time.NewTicker(time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()))
|
|
||||||
defer timer.Stop()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-h.ctx.Done():
|
|
||||||
return
|
|
||||||
case <-timer.C:
|
|
||||||
h.refresh()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) Start() error {
|
func (h *DynamicInboundHandler) Start() error {
|
||||||
err := h.refresh()
|
return h.task.Start()
|
||||||
go h.monitor()
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) Close() {
|
func (h *DynamicInboundHandler) Close() error {
|
||||||
h.cancel()
|
return h.task.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) {
|
func (h *DynamicInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) {
|
||||||
|
|
|
@ -99,7 +99,7 @@ func (m *Manager) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) Close() {
|
func (m *Manager) Close() error {
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
defer m.access.Unlock()
|
defer m.access.Unlock()
|
||||||
|
|
||||||
|
@ -111,6 +111,8 @@ func (m *Manager) Close() {
|
||||||
for _, handler := range m.untaggedHandler {
|
for _, handler := range m.untaggedHandler {
|
||||||
handler.Close()
|
handler.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (core.InboundHandler, error) {
|
func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (core.InboundHandler, error) {
|
||||||
|
|
|
@ -9,8 +9,10 @@ import (
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/app/proxyman"
|
"v2ray.com/core/app/proxyman"
|
||||||
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
|
"v2ray.com/core/common/signal"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
"v2ray.com/core/transport/internet"
|
"v2ray.com/core/transport/internet"
|
||||||
"v2ray.com/core/transport/internet/tcp"
|
"v2ray.com/core/transport/internet/tcp"
|
||||||
|
@ -19,7 +21,7 @@ import (
|
||||||
|
|
||||||
type worker interface {
|
type worker interface {
|
||||||
Start() error
|
Start() error
|
||||||
Close()
|
Close() error
|
||||||
Port() net.Port
|
Port() net.Port
|
||||||
Proxy() proxy.Inbound
|
Proxy() proxy.Inbound
|
||||||
}
|
}
|
||||||
|
@ -34,13 +36,11 @@ type tcpWorker struct {
|
||||||
dispatcher core.Dispatcher
|
dispatcher core.Dispatcher
|
||||||
sniffers []proxyman.KnownProtocols
|
sniffers []proxyman.KnownProtocols
|
||||||
|
|
||||||
ctx context.Context
|
hub internet.Listener
|
||||||
cancel context.CancelFunc
|
|
||||||
hub internet.Listener
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *tcpWorker) callback(conn internet.Connection) {
|
func (w *tcpWorker) callback(conn internet.Connection) {
|
||||||
ctx, cancel := context.WithCancel(w.ctx)
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
if w.recvOrigDest {
|
if w.recvOrigDest {
|
||||||
dest, err := tcp.GetOriginalDestination(conn)
|
dest, err := tcp.GetOriginalDestination(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -70,45 +70,24 @@ func (w *tcpWorker) Proxy() proxy.Inbound {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *tcpWorker) Start() error {
|
func (w *tcpWorker) Start() error {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx := internet.ContextWithStreamSettings(context.Background(), w.stream)
|
||||||
w.ctx = ctx
|
hub, err := internet.ListenTCP(ctx, w.address, w.port, func(conn internet.Connection) {
|
||||||
w.cancel = cancel
|
go w.callback(conn)
|
||||||
ctx = internet.ContextWithStreamSettings(ctx, w.stream)
|
})
|
||||||
conns := make(chan internet.Connection, 16)
|
|
||||||
hub, err := internet.ListenTCP(ctx, w.address, w.port, conns)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError("failed to listen TCP on ", w.port).AtWarning().Base(err)
|
return newError("failed to listen TCP on ", w.port).AtWarning().Base(err)
|
||||||
}
|
}
|
||||||
go w.handleConnections(conns)
|
|
||||||
w.hub = hub
|
w.hub = hub
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *tcpWorker) handleConnections(conns <-chan internet.Connection) {
|
func (w *tcpWorker) Close() error {
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-w.ctx.Done():
|
|
||||||
w.hub.Close()
|
|
||||||
L:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case conn := <-conns:
|
|
||||||
conn.Close()
|
|
||||||
default:
|
|
||||||
break L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case conn := <-conns:
|
|
||||||
go w.callback(conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *tcpWorker) Close() {
|
|
||||||
if w.hub != nil {
|
if w.hub != nil {
|
||||||
w.cancel()
|
common.Close(w.hub)
|
||||||
|
common.Close(w.proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *tcpWorker) Port() net.Port {
|
func (w *tcpWorker) Port() net.Port {
|
||||||
|
@ -121,8 +100,7 @@ type udpConn struct {
|
||||||
output func([]byte) (int, error)
|
output func([]byte) (int, error)
|
||||||
remote net.Addr
|
remote net.Addr
|
||||||
local net.Addr
|
local net.Addr
|
||||||
ctx context.Context
|
done *signal.Done
|
||||||
cancel context.CancelFunc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpConn) updateActivity() {
|
func (c *udpConn) updateActivity() {
|
||||||
|
@ -135,7 +113,7 @@ func (c *udpConn) Read(buf []byte) (int, error) {
|
||||||
defer in.Release()
|
defer in.Release()
|
||||||
c.updateActivity()
|
c.updateActivity()
|
||||||
return copy(buf, in.Bytes()), nil
|
return copy(buf, in.Bytes()), nil
|
||||||
case <-c.ctx.Done():
|
case <-c.done.C():
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,6 +128,7 @@ func (c *udpConn) Write(buf []byte) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpConn) Close() error {
|
func (c *udpConn) Close() error {
|
||||||
|
common.Close(c.done)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +168,7 @@ type udpWorker struct {
|
||||||
tag string
|
tag string
|
||||||
dispatcher core.Dispatcher
|
dispatcher core.Dispatcher
|
||||||
|
|
||||||
ctx context.Context
|
done *signal.Done
|
||||||
cancel context.CancelFunc
|
|
||||||
activeConn map[connId]*udpConn
|
activeConn map[connId]*udpConn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +193,7 @@ func (w *udpWorker) getConnection(id connId) (*udpConn, bool) {
|
||||||
IP: w.address.IP(),
|
IP: w.address.IP(),
|
||||||
Port: int(w.port),
|
Port: int(w.port),
|
||||||
},
|
},
|
||||||
|
done: signal.NewDone(),
|
||||||
}
|
}
|
||||||
w.activeConn[id] = conn
|
w.activeConn[id] = conn
|
||||||
|
|
||||||
|
@ -230,16 +209,15 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
||||||
conn, existing := w.getConnection(id)
|
conn, existing := w.getConnection(id)
|
||||||
select {
|
select {
|
||||||
case conn.input <- b:
|
case conn.input <- b:
|
||||||
|
case <-conn.done.C():
|
||||||
|
b.Release()
|
||||||
default:
|
default:
|
||||||
b.Release()
|
b.Release()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !existing {
|
if !existing {
|
||||||
go func() {
|
go func() {
|
||||||
ctx := w.ctx
|
ctx := context.Background()
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
|
||||||
conn.ctx = ctx
|
|
||||||
conn.cancel = cancel
|
|
||||||
if originalDest.IsValid() {
|
if originalDest.IsValid() {
|
||||||
ctx = proxy.ContextWithOriginalTarget(ctx, originalDest)
|
ctx = proxy.ContextWithOriginalTarget(ctx, originalDest)
|
||||||
}
|
}
|
||||||
|
@ -251,8 +229,8 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
||||||
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
|
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
|
||||||
newError("connection ends").Base(err).WriteToLog()
|
newError("connection ends").Base(err).WriteToLog()
|
||||||
}
|
}
|
||||||
|
conn.Close()
|
||||||
w.removeConn(id)
|
w.removeConn(id)
|
||||||
cancel()
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,9 +243,7 @@ func (w *udpWorker) removeConn(id connId) {
|
||||||
|
|
||||||
func (w *udpWorker) Start() error {
|
func (w *udpWorker) Start() error {
|
||||||
w.activeConn = make(map[connId]*udpConn, 16)
|
w.activeConn = make(map[connId]*udpConn, 16)
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
w.done = signal.NewDone()
|
||||||
w.ctx = ctx
|
|
||||||
w.cancel = cancel
|
|
||||||
h, err := udp.ListenUDP(w.address, w.port, udp.ListenOption{
|
h, err := udp.ListenUDP(w.address, w.port, udp.ListenOption{
|
||||||
Callback: w.callback,
|
Callback: w.callback,
|
||||||
ReceiveOriginalDest: w.recvOrigDest,
|
ReceiveOriginalDest: w.recvOrigDest,
|
||||||
|
@ -280,11 +256,13 @@ func (w *udpWorker) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *udpWorker) Close() {
|
func (w *udpWorker) Close() error {
|
||||||
if w.hub != nil {
|
if w.hub != nil {
|
||||||
w.hub.Close()
|
w.hub.Close()
|
||||||
w.cancel()
|
w.done.Close()
|
||||||
|
common.Close(w.proxy)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *udpWorker) monitor() {
|
func (w *udpWorker) monitor() {
|
||||||
|
@ -293,7 +271,7 @@ func (w *udpWorker) monitor() {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-w.ctx.Done():
|
case <-w.done.C():
|
||||||
return
|
return
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
nowSec := time.Now().Unix()
|
nowSec := time.Now().Unix()
|
||||||
|
@ -301,7 +279,7 @@ func (w *udpWorker) monitor() {
|
||||||
for addr, conn := range w.activeConn {
|
for addr, conn := range w.activeConn {
|
||||||
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 8 {
|
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 8 {
|
||||||
delete(w.activeConn, addr)
|
delete(w.activeConn, addr)
|
||||||
conn.cancel()
|
conn.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Unlock()
|
w.Unlock()
|
||||||
|
|
|
@ -291,7 +291,8 @@ func (s *Server) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Close() {
|
func (s *Server) Close() error {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerWorker struct {
|
type ServerWorker struct {
|
||||||
|
|
|
@ -103,12 +103,12 @@ func (m *SessionManager) CloseIfNoSession() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SessionManager) Close() {
|
func (m *SessionManager) Close() error {
|
||||||
m.Lock()
|
m.Lock()
|
||||||
defer m.Unlock()
|
defer m.Unlock()
|
||||||
|
|
||||||
if m.closed {
|
if m.closed {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
m.closed = true
|
m.closed = true
|
||||||
|
@ -119,6 +119,7 @@ func (m *SessionManager) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
m.sessions = nil
|
m.sessions = nil
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Session represents a client connection in a Mux connection.
|
// Session represents a client connection in a Mux connection.
|
||||||
|
@ -131,10 +132,11 @@ type Session struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes all resources associated with this session.
|
// Close closes all resources associated with this session.
|
||||||
func (s *Session) Close() {
|
func (s *Session) Close() error {
|
||||||
s.output.Close()
|
s.output.Close()
|
||||||
s.input.Close()
|
s.input.Close()
|
||||||
s.parent.Remove(s.ID)
|
s.parent.Remove(s.ID)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReader creates a buf.Reader based on the transfer type of this Session.
|
// NewReader creates a buf.Reader based on the transfer type of this Session.
|
||||||
|
|
|
@ -100,7 +100,7 @@ func (w *Writer) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Close() {
|
func (w *Writer) Close() error {
|
||||||
meta := FrameMetadata{
|
meta := FrameMetadata{
|
||||||
SessionID: w.id,
|
SessionID: w.id,
|
||||||
SessionStatus: SessionStatusEnd,
|
SessionStatus: SessionStatusEnd,
|
||||||
|
@ -110,4 +110,5 @@ func (w *Writer) Close() {
|
||||||
common.Must(frame.Reset(meta.AsSupplier()))
|
common.Must(frame.Reset(meta.AsSupplier()))
|
||||||
|
|
||||||
w.writer.WriteMultiBuffer(buf.NewMultiBufferValue(frame))
|
w.writer.WriteMultiBuffer(buf.NewMultiBufferValue(frame))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ func New(ctx context.Context, config *proxyman.OutboundConfig) (*Manager, error)
|
||||||
func (*Manager) Start() error { return nil }
|
func (*Manager) Start() error { return nil }
|
||||||
|
|
||||||
// Close implements core.Feature
|
// Close implements core.Feature
|
||||||
func (*Manager) Close() {}
|
func (*Manager) Close() error { return nil }
|
||||||
|
|
||||||
// GetDefaultHandler implements core.OutboundHandlerManager.
|
// GetDefaultHandler implements core.OutboundHandlerManager.
|
||||||
func (m *Manager) GetDefaultHandler() core.OutboundHandler {
|
func (m *Manager) GetDefaultHandler() core.OutboundHandler {
|
||||||
|
|
|
@ -114,7 +114,9 @@ func (*Router) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Router) Close() {}
|
func (*Router) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
|
|
6
clock.go
6
clock.go
|
@ -40,15 +40,15 @@ func (c *syncClock) Start() error {
|
||||||
return c.Clock.Start()
|
return c.Clock.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *syncClock) Close() {
|
func (c *syncClock) Close() error {
|
||||||
c.RLock()
|
c.RLock()
|
||||||
defer c.RUnlock()
|
defer c.RUnlock()
|
||||||
|
|
||||||
if c.Clock == nil {
|
if c.Clock == nil {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Clock.Close()
|
return c.Clock.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *syncClock) Set(clock Clock) {
|
func (c *syncClock) Set(clock Clock) {
|
||||||
|
|
|
@ -44,15 +44,15 @@ func (c *syncCommander) Start() error {
|
||||||
return c.Commander.Start()
|
return c.Commander.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *syncCommander) Close() {
|
func (c *syncCommander) Close() error {
|
||||||
c.RLock()
|
c.RLock()
|
||||||
defer c.RUnlock()
|
defer c.RUnlock()
|
||||||
|
|
||||||
if c.Commander == nil {
|
if c.Commander == nil {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Commander.Close()
|
return c.Commander.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *syncCommander) Set(commander Commander) {
|
func (c *syncCommander) Set(commander Commander) {
|
||||||
|
|
|
@ -1,10 +1,23 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
|
// Closable is the interface for objects that can release its resources.
|
||||||
|
type Closable interface {
|
||||||
|
// Close release all resources used by this object, including goroutines.
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the obj if it is a Closable.
|
||||||
|
func Close(obj interface{}) error {
|
||||||
|
if c, ok := obj.(Closable); ok {
|
||||||
|
return c.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Runnable is the interface for objects that can start to work and stop on demand.
|
// Runnable is the interface for objects that can start to work and stop on demand.
|
||||||
type Runnable interface {
|
type Runnable interface {
|
||||||
// Start starts the runnable object. Upon the method returning nil, the object begins to function properly.
|
// Start starts the runnable object. Upon the method returning nil, the object begins to function properly.
|
||||||
Start() error
|
Start() error
|
||||||
|
|
||||||
// Close stops the object being working.
|
Closable
|
||||||
Close()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package signal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Done struct {
|
||||||
|
access sync.Mutex
|
||||||
|
c chan struct{}
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDone() *Done {
|
||||||
|
return &Done{
|
||||||
|
c: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Done) Done() bool {
|
||||||
|
select {
|
||||||
|
case <-d.c:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Done) C() chan struct{} {
|
||||||
|
return d.c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Done) Wait() {
|
||||||
|
<-d.c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Done) Close() error {
|
||||||
|
d.access.Lock()
|
||||||
|
defer d.access.Unlock()
|
||||||
|
|
||||||
|
if d.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d.closed = true
|
||||||
|
close(d.c)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,22 +1,22 @@
|
||||||
package signal
|
package signal
|
||||||
|
|
||||||
type Notifier struct {
|
type Notifier struct {
|
||||||
c chan bool
|
c chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNotifier() *Notifier {
|
func NewNotifier() *Notifier {
|
||||||
return &Notifier{
|
return &Notifier{
|
||||||
c: make(chan bool, 1),
|
c: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notifier) Signal() {
|
func (n *Notifier) Signal() {
|
||||||
select {
|
select {
|
||||||
case n.c <- true:
|
case n.c <- struct{}{}:
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notifier) Wait() <-chan bool {
|
func (n *Notifier) Wait() <-chan struct{} {
|
||||||
return n.c
|
return n.c
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
package signal
|
package signal
|
||||||
|
|
||||||
type Semaphore struct {
|
type Semaphore struct {
|
||||||
token chan bool
|
token chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSemaphore(n int) *Semaphore {
|
func NewSemaphore(n int) *Semaphore {
|
||||||
s := &Semaphore{
|
s := &Semaphore{
|
||||||
token: make(chan bool, n),
|
token: make(chan struct{}, n),
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
s.token <- true
|
s.token <- struct{}{}
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Semaphore) Wait() <-chan bool {
|
func (s *Semaphore) Wait() <-chan struct{} {
|
||||||
return s.token
|
return s.token
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Semaphore) Signal() {
|
func (s *Semaphore) Signal() {
|
||||||
s.token <- true
|
s.token <- struct{}{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
package signal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PeriodicTask struct {
|
||||||
|
Interval time.Duration
|
||||||
|
Execute func() error
|
||||||
|
|
||||||
|
access sync.Mutex
|
||||||
|
timer *time.Timer
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PeriodicTask) checkedExecute() error {
|
||||||
|
t.access.Lock()
|
||||||
|
defer t.access.Unlock()
|
||||||
|
|
||||||
|
if t.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.Execute(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t.timer = time.AfterFunc(t.Interval, func() {
|
||||||
|
t.checkedExecute()
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PeriodicTask) Start() error {
|
||||||
|
t.access.Lock()
|
||||||
|
t.closed = false
|
||||||
|
t.access.Unlock()
|
||||||
|
|
||||||
|
if err := t.checkedExecute(); err != nil {
|
||||||
|
t.closed = true
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PeriodicTask) Close() error {
|
||||||
|
t.access.Lock()
|
||||||
|
defer t.access.Unlock()
|
||||||
|
|
||||||
|
t.closed = true
|
||||||
|
if t.timer != nil {
|
||||||
|
t.timer.Stop()
|
||||||
|
t.timer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -10,14 +10,14 @@ type ActivityUpdater interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActivityTimer struct {
|
type ActivityTimer struct {
|
||||||
updated chan bool
|
updated chan struct{}
|
||||||
timeout chan time.Duration
|
timeout chan time.Duration
|
||||||
closing chan bool
|
closing chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ActivityTimer) Update() {
|
func (t *ActivityTimer) Update() {
|
||||||
select {
|
select {
|
||||||
case t.updated <- true:
|
case t.updated <- struct{}{}:
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,8 @@ func (t *ActivityTimer) run(ctx context.Context, cancel context.CancelFunc) {
|
||||||
func CancelAfterInactivity(ctx context.Context, cancel context.CancelFunc, timeout time.Duration) *ActivityTimer {
|
func CancelAfterInactivity(ctx context.Context, cancel context.CancelFunc, timeout time.Duration) *ActivityTimer {
|
||||||
timer := &ActivityTimer{
|
timer := &ActivityTimer{
|
||||||
timeout: make(chan time.Duration, 1),
|
timeout: make(chan time.Duration, 1),
|
||||||
updated: make(chan bool, 1),
|
updated: make(chan struct{}, 1),
|
||||||
closing: make(chan bool),
|
closing: make(chan struct{}),
|
||||||
}
|
}
|
||||||
timer.timeout <- timeout
|
timer.timeout <- timeout
|
||||||
go timer.run(ctx, cancel)
|
go timer.run(ctx, cancel)
|
||||||
|
|
14
dns.go
14
dns.go
|
@ -1,7 +1,11 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
import "sync"
|
"net"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"v2ray.com/core/common"
|
||||||
|
)
|
||||||
|
|
||||||
// DNSClient is a V2Ray feature for querying DNS information.
|
// DNSClient is a V2Ray feature for querying DNS information.
|
||||||
type DNSClient interface {
|
type DNSClient interface {
|
||||||
|
@ -36,13 +40,11 @@ func (d *syncDNSClient) Start() error {
|
||||||
return d.DNSClient.Start()
|
return d.DNSClient.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *syncDNSClient) Close() {
|
func (d *syncDNSClient) Close() error {
|
||||||
d.RLock()
|
d.RLock()
|
||||||
defer d.RUnlock()
|
defer d.RUnlock()
|
||||||
|
|
||||||
if d.DNSClient != nil {
|
return common.Close(d.DNSClient)
|
||||||
d.DNSClient.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *syncDNSClient) Set(client DNSClient) {
|
func (d *syncDNSClient) Set(client DNSClient) {
|
||||||
|
|
13
network.go
13
network.go
|
@ -21,6 +21,7 @@ type InboundHandler interface {
|
||||||
|
|
||||||
// OutboundHandler is the interface for handlers that process outbound connections.
|
// OutboundHandler is the interface for handlers that process outbound connections.
|
||||||
type OutboundHandler interface {
|
type OutboundHandler interface {
|
||||||
|
common.Runnable
|
||||||
Tag() string
|
Tag() string
|
||||||
Dispatch(ctx context.Context, outboundRay ray.OutboundRay)
|
Dispatch(ctx context.Context, outboundRay ray.OutboundRay)
|
||||||
}
|
}
|
||||||
|
@ -75,13 +76,11 @@ func (m *syncInboundHandlerManager) Start() error {
|
||||||
return m.InboundHandlerManager.Start()
|
return m.InboundHandlerManager.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *syncInboundHandlerManager) Close() {
|
func (m *syncInboundHandlerManager) Close() error {
|
||||||
m.RLock()
|
m.RLock()
|
||||||
defer m.RUnlock()
|
defer m.RUnlock()
|
||||||
|
|
||||||
if m.InboundHandlerManager != nil {
|
return common.Close(m.InboundHandlerManager)
|
||||||
m.InboundHandlerManager.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *syncInboundHandlerManager) Set(manager InboundHandlerManager) {
|
func (m *syncInboundHandlerManager) Set(manager InboundHandlerManager) {
|
||||||
|
@ -154,13 +153,11 @@ func (m *syncOutboundHandlerManager) Start() error {
|
||||||
return m.OutboundHandlerManager.Start()
|
return m.OutboundHandlerManager.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *syncOutboundHandlerManager) Close() {
|
func (m *syncOutboundHandlerManager) Close() error {
|
||||||
m.RLock()
|
m.RLock()
|
||||||
defer m.RUnlock()
|
defer m.RUnlock()
|
||||||
|
|
||||||
if m.OutboundHandlerManager != nil {
|
return common.Close(m.OutboundHandlerManager)
|
||||||
m.OutboundHandlerManager.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *syncOutboundHandlerManager) Set(manager OutboundHandlerManager) {
|
func (m *syncOutboundHandlerManager) Set(manager OutboundHandlerManager) {
|
||||||
|
|
|
@ -3,6 +3,8 @@ package core
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"v2ray.com/core/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TimeoutPolicy contains limits for connection timeout.
|
// TimeoutPolicy contains limits for connection timeout.
|
||||||
|
@ -96,13 +98,11 @@ func (m *syncPolicyManager) Start() error {
|
||||||
return m.PolicyManager.Start()
|
return m.PolicyManager.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *syncPolicyManager) Close() {
|
func (m *syncPolicyManager) Close() error {
|
||||||
m.RLock()
|
m.RLock()
|
||||||
defer m.RUnlock()
|
defer m.RUnlock()
|
||||||
|
|
||||||
if m.PolicyManager != nil {
|
return common.Close(m.PolicyManager)
|
||||||
m.PolicyManager.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *syncPolicyManager) Set(manager PolicyManager) {
|
func (m *syncPolicyManager) Set(manager PolicyManager) {
|
||||||
|
|
|
@ -48,8 +48,9 @@ func TestRequestSerialization(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
sessionHistory := NewSessionHistory()
|
sessionHistory := NewSessionHistory()
|
||||||
|
|
||||||
userValidator := vmess.NewTimedUserValidator(ctx, protocol.DefaultIDHash)
|
userValidator := vmess.NewTimedUserValidator(protocol.DefaultIDHash)
|
||||||
userValidator.Add(user)
|
userValidator.Add(user)
|
||||||
|
defer common.Close(userValidator)
|
||||||
|
|
||||||
server := NewServerSession(userValidator, sessionHistory)
|
server := NewServerSession(userValidator, sessionHistory)
|
||||||
actualRequest, err := server.DecodeRequestHeader(buffer)
|
actualRequest, err := server.DecodeRequestHeader(buffer)
|
||||||
|
|
|
@ -30,28 +30,34 @@ type sessionId struct {
|
||||||
type SessionHistory struct {
|
type SessionHistory struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
cache map[sessionId]time.Time
|
cache map[sessionId]time.Time
|
||||||
token *signal.Semaphore
|
task *signal.PeriodicTask
|
||||||
timer *time.Timer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSessionHistory() *SessionHistory {
|
func NewSessionHistory() *SessionHistory {
|
||||||
h := &SessionHistory{
|
h := &SessionHistory{
|
||||||
cache: make(map[sessionId]time.Time, 128),
|
cache: make(map[sessionId]time.Time, 128),
|
||||||
token: signal.NewSemaphore(1),
|
|
||||||
}
|
}
|
||||||
|
h.task = &signal.PeriodicTask{
|
||||||
|
Interval: time.Second * 30,
|
||||||
|
Execute: func() error {
|
||||||
|
h.removeExpiredEntries()
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
common.Must(h.task.Start())
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close implements common.Closable.
|
||||||
|
func (h *SessionHistory) Close() error {
|
||||||
|
return h.task.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (h *SessionHistory) add(session sessionId) {
|
func (h *SessionHistory) add(session sessionId) {
|
||||||
h.Lock()
|
h.Lock()
|
||||||
defer h.Unlock()
|
defer h.Unlock()
|
||||||
|
|
||||||
h.cache[session] = time.Now().Add(time.Minute * 3)
|
h.cache[session] = time.Now().Add(time.Minute * 3)
|
||||||
select {
|
|
||||||
case <-h.token.Wait():
|
|
||||||
h.timer = time.AfterFunc(time.Minute*3, h.removeExpiredEntries)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SessionHistory) has(session sessionId) bool {
|
func (h *SessionHistory) has(session sessionId) bool {
|
||||||
|
@ -75,11 +81,6 @@ func (h *SessionHistory) removeExpiredEntries() {
|
||||||
delete(h.cache, session)
|
delete(h.cache, session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.timer != nil {
|
|
||||||
h.timer.Stop()
|
|
||||||
h.timer = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerSession struct {
|
type ServerSession struct {
|
||||||
|
|
|
@ -90,7 +90,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||||
handler := &Handler{
|
handler := &Handler{
|
||||||
policyManager: v.PolicyManager(),
|
policyManager: v.PolicyManager(),
|
||||||
inboundHandlerManager: v.InboundHandlerManager(),
|
inboundHandlerManager: v.InboundHandlerManager(),
|
||||||
clients: vmess.NewTimedUserValidator(ctx, protocol.DefaultIDHash),
|
clients: vmess.NewTimedUserValidator(protocol.DefaultIDHash),
|
||||||
detours: config.Detour,
|
detours: config.Detour,
|
||||||
usersByEmail: newUserByEmail(config.User, config.GetDefaultValue()),
|
usersByEmail: newUserByEmail(config.User, config.GetDefaultValue()),
|
||||||
sessionHistory: encoding.NewSessionHistory(),
|
sessionHistory: encoding.NewSessionHistory(),
|
||||||
|
@ -105,6 +105,14 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||||
return handler, nil
|
return handler, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close implements common.Closable.
|
||||||
|
func (h *Handler) Close() error {
|
||||||
|
common.Close(h.clients)
|
||||||
|
common.Close(h.sessionHistory)
|
||||||
|
common.Close(h.usersByEmail)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Network implements proxy.Inbound.Network().
|
// Network implements proxy.Inbound.Network().
|
||||||
func (*Handler) Network() net.NetworkList {
|
func (*Handler) Network() net.NetworkList {
|
||||||
return net.NetworkList{
|
return net.NetworkList{
|
||||||
|
|
|
@ -8,17 +8,17 @@ package vmess
|
||||||
//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg vmess -path Proxy,VMess
|
//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg vmess -path Proxy,VMess
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/protocol"
|
"v2ray.com/core/common/protocol"
|
||||||
|
"v2ray.com/core/common/signal"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
updateIntervalSec = 10
|
updateInterval = 10 * time.Second
|
||||||
cacheDurationSec = 120
|
cacheDurationSec = 120
|
||||||
)
|
)
|
||||||
|
|
||||||
type idEntry struct {
|
type idEntry struct {
|
||||||
|
@ -34,6 +34,7 @@ type TimedUserValidator struct {
|
||||||
ids []*idEntry
|
ids []*idEntry
|
||||||
hasher protocol.IDHash
|
hasher protocol.IDHash
|
||||||
baseTime protocol.Timestamp
|
baseTime protocol.Timestamp
|
||||||
|
task *signal.PeriodicTask
|
||||||
}
|
}
|
||||||
|
|
||||||
type indexTimePair struct {
|
type indexTimePair struct {
|
||||||
|
@ -41,16 +42,23 @@ type indexTimePair struct {
|
||||||
timeInc uint32
|
timeInc uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTimedUserValidator(ctx context.Context, hasher protocol.IDHash) protocol.UserValidator {
|
func NewTimedUserValidator(hasher protocol.IDHash) protocol.UserValidator {
|
||||||
tus := &TimedUserValidator{
|
tuv := &TimedUserValidator{
|
||||||
validUsers: make([]*protocol.User, 0, 16),
|
validUsers: make([]*protocol.User, 0, 16),
|
||||||
userHash: make(map[[16]byte]indexTimePair, 512),
|
userHash: make(map[[16]byte]indexTimePair, 512),
|
||||||
ids: make([]*idEntry, 0, 512),
|
ids: make([]*idEntry, 0, 512),
|
||||||
hasher: hasher,
|
hasher: hasher,
|
||||||
baseTime: protocol.Timestamp(time.Now().Unix() - cacheDurationSec*3),
|
baseTime: protocol.Timestamp(time.Now().Unix() - cacheDurationSec*3),
|
||||||
}
|
}
|
||||||
go tus.updateUserHash(ctx, updateIntervalSec*time.Second)
|
tuv.task = &signal.PeriodicTask{
|
||||||
return tus
|
Interval: updateInterval,
|
||||||
|
Execute: func() error {
|
||||||
|
tuv.updateUserHash()
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tuv.task.Start()
|
||||||
|
return tuv
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *TimedUserValidator) generateNewHashes(nowSec protocol.Timestamp, idx int, entry *idEntry) {
|
func (v *TimedUserValidator) generateNewHashes(nowSec protocol.Timestamp, idx int, entry *idEntry) {
|
||||||
|
@ -78,24 +86,19 @@ func (v *TimedUserValidator) removeExpiredHashes(expire uint32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *TimedUserValidator) updateUserHash(ctx context.Context, interval time.Duration) {
|
func (v *TimedUserValidator) updateUserHash() {
|
||||||
for {
|
now := time.Now()
|
||||||
select {
|
nowSec := protocol.Timestamp(now.Unix() + cacheDurationSec)
|
||||||
case now := <-time.After(interval):
|
v.Lock()
|
||||||
nowSec := protocol.Timestamp(now.Unix() + cacheDurationSec)
|
defer v.Unlock()
|
||||||
v.Lock()
|
|
||||||
for _, entry := range v.ids {
|
|
||||||
v.generateNewHashes(nowSec, entry.userIdx, entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
expire := protocol.Timestamp(now.Unix() - cacheDurationSec*3)
|
for _, entry := range v.ids {
|
||||||
if expire > v.baseTime {
|
v.generateNewHashes(nowSec, entry.userIdx, entry)
|
||||||
v.removeExpiredHashes(uint32(expire - v.baseTime))
|
}
|
||||||
}
|
|
||||||
v.Unlock()
|
expire := protocol.Timestamp(now.Unix() - cacheDurationSec*3)
|
||||||
case <-ctx.Done():
|
if expire > v.baseTime {
|
||||||
return
|
v.removeExpiredHashes(uint32(expire - v.baseTime))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,3 +148,8 @@ func (v *TimedUserValidator) Get(userHash []byte) (*protocol.User, protocol.Time
|
||||||
}
|
}
|
||||||
return nil, 0, false
|
return nil, 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close implements common.Closable.
|
||||||
|
func (v *TimedUserValidator) Close() error {
|
||||||
|
return v.task.Close()
|
||||||
|
}
|
||||||
|
|
13
router.go
13
router.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/transport/ray"
|
"v2ray.com/core/transport/ray"
|
||||||
|
@ -45,13 +46,11 @@ func (d *syncDispatcher) Start() error {
|
||||||
return d.Dispatcher.Start()
|
return d.Dispatcher.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *syncDispatcher) Close() {
|
func (d *syncDispatcher) Close() error {
|
||||||
d.RLock()
|
d.RLock()
|
||||||
defer d.RUnlock()
|
defer d.RUnlock()
|
||||||
|
|
||||||
if d.Dispatcher != nil {
|
return common.Close(d.Dispatcher)
|
||||||
d.Dispatcher.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *syncDispatcher) Set(disp Dispatcher) {
|
func (d *syncDispatcher) Set(disp Dispatcher) {
|
||||||
|
@ -101,13 +100,11 @@ func (r *syncRouter) Start() error {
|
||||||
return r.Router.Start()
|
return r.Router.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *syncRouter) Close() {
|
func (r *syncRouter) Close() error {
|
||||||
r.RLock()
|
r.RLock()
|
||||||
defer r.RUnlock()
|
defer r.RUnlock()
|
||||||
|
|
||||||
if r.Router != nil {
|
return common.Close(r.Router)
|
||||||
r.Router.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *syncRouter) Set(router Router) {
|
func (r *syncRouter) Set(router Router) {
|
||||||
|
|
|
@ -36,6 +36,6 @@ func (s *Server) Start() (net.Destination, error) {
|
||||||
return net.TCPDestination(net.LocalHostIP, net.Port(s.Port)), nil
|
return net.TCPDestination(net.LocalHostIP, net.Port(s.Port)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Close() {
|
func (s *Server) Close() error {
|
||||||
s.server.Close()
|
return s.server.Close()
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,6 @@ func (server *Server) handleConnection(conn net.Conn) {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) Close() {
|
func (server *Server) Close() error {
|
||||||
server.listener.Close()
|
return server.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ func (server *Server) handleConnection(conn *net.UDPConn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) Close() {
|
func (server *Server) Close() error {
|
||||||
server.accepting = false
|
server.accepting = false
|
||||||
server.conn.Close()
|
return server.conn.Close()
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ type ConnectionID struct {
|
||||||
// Listener defines a server listening for connections
|
// Listener defines a server listening for connections
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
ctx context.Context
|
|
||||||
sessions map[ConnectionID]*Connection
|
sessions map[ConnectionID]*Connection
|
||||||
hub *udp.Hub
|
hub *udp.Hub
|
||||||
tlsConfig *tls.Config
|
tlsConfig *tls.Config
|
||||||
|
@ -31,10 +30,10 @@ type Listener struct {
|
||||||
reader PacketReader
|
reader PacketReader
|
||||||
header internet.PacketHeader
|
header internet.PacketHeader
|
||||||
security cipher.AEAD
|
security cipher.AEAD
|
||||||
addConn internet.AddConnection
|
addConn internet.ConnHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewListener(ctx context.Context, address net.Address, port net.Port, addConn internet.AddConnection) (*Listener, error) {
|
func NewListener(ctx context.Context, address net.Address, port net.Port, addConn internet.ConnHandler) (*Listener, error) {
|
||||||
networkSettings := internet.TransportSettingsFromContext(ctx)
|
networkSettings := internet.TransportSettingsFromContext(ctx)
|
||||||
kcpSettings := networkSettings.(*Config)
|
kcpSettings := networkSettings.(*Config)
|
||||||
|
|
||||||
|
@ -54,7 +53,6 @@ func NewListener(ctx context.Context, address net.Address, port net.Port, addCon
|
||||||
Security: security,
|
Security: security,
|
||||||
},
|
},
|
||||||
sessions: make(map[ConnectionID]*Connection),
|
sessions: make(map[ConnectionID]*Connection),
|
||||||
ctx: ctx,
|
|
||||||
config: kcpSettings,
|
config: kcpSettings,
|
||||||
addConn: addConn,
|
addConn: addConn,
|
||||||
}
|
}
|
||||||
|
@ -86,12 +84,6 @@ func (l *Listener) OnReceive(payload *buf.Buffer, src net.Destination, originalD
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
|
|
||||||
select {
|
|
||||||
case <-l.ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
if l.hub == nil {
|
if l.hub == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -136,23 +128,16 @@ func (l *Listener) OnReceive(payload *buf.Buffer, src net.Destination, originalD
|
||||||
netConn = tlsConn
|
netConn = tlsConn
|
||||||
}
|
}
|
||||||
|
|
||||||
if !l.addConn(context.Background(), netConn) {
|
l.addConn(netConn)
|
||||||
return
|
|
||||||
}
|
|
||||||
l.sessions[id] = conn
|
l.sessions[id] = conn
|
||||||
}
|
}
|
||||||
conn.Input(segments)
|
conn.Input(segments)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) Remove(id ConnectionID) {
|
func (l *Listener) Remove(id ConnectionID) {
|
||||||
select {
|
l.Lock()
|
||||||
case <-l.ctx.Done():
|
delete(l.sessions, id)
|
||||||
return
|
l.Unlock()
|
||||||
default:
|
|
||||||
l.Lock()
|
|
||||||
delete(l.sessions, id)
|
|
||||||
l.Unlock()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close stops listening on the UDP address. Already Accepted connections are not closed.
|
// Close stops listening on the UDP address. Already Accepted connections are not closed.
|
||||||
|
@ -197,7 +182,7 @@ func (w *Writer) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenKCP(ctx context.Context, address net.Address, port net.Port, addConn internet.AddConnection) (internet.Listener, error) {
|
func ListenKCP(ctx context.Context, address net.Address, port net.Port, addConn internet.ConnHandler) (internet.Listener, error) {
|
||||||
return NewListener(ctx, address, port, addConn)
|
return NewListener(ctx, address, port, addConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@ package tcp
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
gotls "crypto/tls"
|
gotls "crypto/tls"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/retry"
|
|
||||||
"v2ray.com/core/transport/internet"
|
"v2ray.com/core/transport/internet"
|
||||||
"v2ray.com/core/transport/internet/tls"
|
"v2ray.com/core/transport/internet/tls"
|
||||||
)
|
)
|
||||||
|
@ -17,11 +17,11 @@ type Listener struct {
|
||||||
tlsConfig *gotls.Config
|
tlsConfig *gotls.Config
|
||||||
authConfig internet.ConnectionAuthenticator
|
authConfig internet.ConnectionAuthenticator
|
||||||
config *Config
|
config *Config
|
||||||
addConn internet.AddConnection
|
addConn internet.ConnHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenTCP creates a new Listener based on configurations.
|
// ListenTCP creates a new Listener based on configurations.
|
||||||
func ListenTCP(ctx context.Context, address net.Address, port net.Port, addConn internet.AddConnection) (internet.Listener, error) {
|
func ListenTCP(ctx context.Context, address net.Address, port net.Port, handler internet.ConnHandler) (internet.Listener, error) {
|
||||||
listener, err := net.ListenTCP("tcp", &net.TCPAddr{
|
listener, err := net.ListenTCP("tcp", &net.TCPAddr{
|
||||||
IP: address.IP(),
|
IP: address.IP(),
|
||||||
Port: int(port),
|
Port: int(port),
|
||||||
|
@ -36,7 +36,7 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, addConn
|
||||||
l := &Listener{
|
l := &Listener{
|
||||||
listener: listener,
|
listener: listener,
|
||||||
config: tcpSettings,
|
config: tcpSettings,
|
||||||
addConn: addConn,
|
addConn: handler,
|
||||||
}
|
}
|
||||||
|
|
||||||
if config := tls.ConfigFromContext(ctx, tls.WithNextProto("h2")); config != nil {
|
if config := tls.ConfigFromContext(ctx, tls.WithNextProto("h2")); config != nil {
|
||||||
|
@ -54,27 +54,17 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, addConn
|
||||||
}
|
}
|
||||||
l.authConfig = auth
|
l.authConfig = auth
|
||||||
}
|
}
|
||||||
go l.keepAccepting(ctx)
|
go l.keepAccepting()
|
||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Listener) keepAccepting(ctx context.Context) {
|
func (v *Listener) keepAccepting() {
|
||||||
for {
|
for {
|
||||||
select {
|
conn, err := v.listener.Accept()
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
var conn net.Conn
|
|
||||||
err := retry.ExponentialBackoff(5, 200).On(func() error {
|
|
||||||
rawConn, err := v.listener.Accept()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
conn = rawConn
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "closed") {
|
||||||
|
break
|
||||||
|
}
|
||||||
newError("failed to accepted raw connections").Base(err).AtWarning().WriteToLog()
|
newError("failed to accepted raw connections").Base(err).AtWarning().WriteToLog()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -86,7 +76,7 @@ func (v *Listener) keepAccepting(ctx context.Context) {
|
||||||
conn = v.authConfig.Server(conn)
|
conn = v.authConfig.Server(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.addConn(context.Background(), internet.Connection(conn))
|
v.addConn(internet.Connection(conn))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package internet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
)
|
)
|
||||||
|
@ -19,16 +18,16 @@ func RegisterTransportListener(protocol TransportProtocol, listener ListenFunc)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddConnection func(context.Context, Connection) bool
|
type ConnHandler func(Connection)
|
||||||
|
|
||||||
type ListenFunc func(ctx context.Context, address net.Address, port net.Port, addConn AddConnection) (Listener, error)
|
type ListenFunc func(ctx context.Context, address net.Address, port net.Port, handler ConnHandler) (Listener, error)
|
||||||
|
|
||||||
type Listener interface {
|
type Listener interface {
|
||||||
Close() error
|
Close() error
|
||||||
Addr() net.Addr
|
Addr() net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenTCP(ctx context.Context, address net.Address, port net.Port, conns chan<- Connection) (Listener, error) {
|
func ListenTCP(ctx context.Context, address net.Address, port net.Port, handler ConnHandler) (Listener, error) {
|
||||||
settings := StreamSettingsFromContext(ctx)
|
settings := StreamSettingsFromContext(ctx)
|
||||||
protocol := settings.GetEffectiveProtocol()
|
protocol := settings.GetEffectiveProtocol()
|
||||||
transportSettings, err := settings.GetEffectiveTransportSettings()
|
transportSettings, err := settings.GetEffectiveTransportSettings()
|
||||||
|
@ -47,26 +46,7 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, conns ch
|
||||||
if listenFunc == nil {
|
if listenFunc == nil {
|
||||||
return nil, newError(protocol, " listener not registered.").AtError()
|
return nil, newError(protocol, " listener not registered.").AtError()
|
||||||
}
|
}
|
||||||
listener, err := listenFunc(ctx, address, port, func(ctx context.Context, conn Connection) bool {
|
listener, err := listenFunc(ctx, address, port, handler)
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
conn.Close()
|
|
||||||
return false
|
|
||||||
case conns <- conn:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
conn.Close()
|
|
||||||
return false
|
|
||||||
case conns <- conn:
|
|
||||||
return true
|
|
||||||
case <-time.After(time.Second * 5):
|
|
||||||
conn.Close()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to listen on address: ", address, ":", port).Base(err)
|
return nil, newError("failed to listen on address: ", address, ":", port).Base(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,9 @@ func (d *TestDispatcher) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *TestDispatcher) Close() {}
|
func (d *TestDispatcher) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestSameDestinationDispatching(t *testing.T) {
|
func TestSameDestinationDispatching(t *testing.T) {
|
||||||
assert := With(t)
|
assert := With(t)
|
||||||
|
|
|
@ -60,10 +60,11 @@ func (q *PayloadQueue) Dequeue(queue <-chan Payload) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *PayloadQueue) Close() {
|
func (q *PayloadQueue) Close() error {
|
||||||
for _, queue := range q.queue {
|
for _, queue := range q.queue {
|
||||||
close(queue)
|
close(queue)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListenOption struct {
|
type ListenOption struct {
|
||||||
|
@ -116,9 +117,10 @@ func ListenUDP(address net.Address, port net.Port, option ListenOption) (*Hub, e
|
||||||
return hub, nil
|
return hub, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hub) Close() {
|
func (h *Hub) Close() error {
|
||||||
h.cancel()
|
h.cancel()
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hub) WriteTo(payload []byte, dest net.Destination) (int, error) {
|
func (h *Hub) WriteTo(payload []byte, dest net.Destination) (int, error) {
|
||||||
|
|
|
@ -44,24 +44,22 @@ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req
|
||||||
remoteAddr.(*net.TCPAddr).IP = forwardedAddrs[0].IP()
|
remoteAddr.(*net.TCPAddr).IP = forwardedAddrs[0].IP()
|
||||||
}
|
}
|
||||||
|
|
||||||
h.ln.addConn(h.ln.ctx, newConnection(conn, remoteAddr))
|
h.ln.addConn(newConnection(conn, remoteAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
ctx context.Context
|
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
tlsConfig *tls.Config
|
tlsConfig *tls.Config
|
||||||
config *Config
|
config *Config
|
||||||
addConn internet.AddConnection
|
addConn internet.ConnHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenWS(ctx context.Context, address net.Address, port net.Port, addConn internet.AddConnection) (internet.Listener, error) {
|
func ListenWS(ctx context.Context, address net.Address, port net.Port, addConn internet.ConnHandler) (internet.Listener, error) {
|
||||||
networkSettings := internet.TransportSettingsFromContext(ctx)
|
networkSettings := internet.TransportSettingsFromContext(ctx)
|
||||||
wsSettings := networkSettings.(*Config)
|
wsSettings := networkSettings.(*Config)
|
||||||
|
|
||||||
l := &Listener{
|
l := &Listener{
|
||||||
ctx: ctx,
|
|
||||||
config: wsSettings,
|
config: wsSettings,
|
||||||
addConn: addConn,
|
addConn: addConn,
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,12 +209,13 @@ func (s *Stream) WriteMultiBuffer(data buf.MultiBuffer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the stream for writing. Read() still works until EOF.
|
// Close closes the stream for writing. Read() still works until EOF.
|
||||||
func (s *Stream) Close() {
|
func (s *Stream) Close() error {
|
||||||
s.access.Lock()
|
s.access.Lock()
|
||||||
s.close = true
|
s.close = true
|
||||||
s.readSignal.Signal()
|
s.readSignal.Signal()
|
||||||
s.writeSignal.Signal()
|
s.writeSignal.Signal()
|
||||||
s.access.Unlock()
|
s.access.Unlock()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloseError closes the Stream with error. Read() will return an error afterwards.
|
// CloseError closes the Stream with error. Read() will return an error afterwards.
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package ray
|
package ray
|
||||||
|
|
||||||
import "v2ray.com/core/common/buf"
|
import (
|
||||||
|
"v2ray.com/core/common"
|
||||||
|
"v2ray.com/core/common/buf"
|
||||||
|
)
|
||||||
|
|
||||||
// OutboundRay is a transport interface for outbound connections.
|
// OutboundRay is a transport interface for outbound connections.
|
||||||
type OutboundRay interface {
|
type OutboundRay interface {
|
||||||
|
@ -34,7 +37,7 @@ type Ray interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RayStream interface {
|
type RayStream interface {
|
||||||
Close()
|
common.Closable
|
||||||
CloseError()
|
CloseError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
v2ray.go
4
v2ray.go
|
@ -101,7 +101,7 @@ func (s *Instance) ID() uuid.UUID {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close shutdown the V2Ray instance.
|
// Close shutdown the V2Ray instance.
|
||||||
func (s *Instance) Close() {
|
func (s *Instance) Close() error {
|
||||||
s.access.Lock()
|
s.access.Lock()
|
||||||
defer s.access.Unlock()
|
defer s.access.Unlock()
|
||||||
|
|
||||||
|
@ -109,6 +109,8 @@ func (s *Instance) Close() {
|
||||||
for _, f := range s.features {
|
for _, f := range s.features {
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown.
|
// Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown.
|
||||||
|
|
Loading…
Reference in New Issue