github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/app/commander/outbound.go (about) 1 // +build !confonly 2 3 package commander 4 5 import ( 6 "context" 7 "sync" 8 9 "v2ray.com/core/common" 10 "v2ray.com/core/common/net" 11 "v2ray.com/core/common/signal/done" 12 "v2ray.com/core/transport" 13 ) 14 15 // OutboundListener is a net.Listener for listening gRPC connections. 16 type OutboundListener struct { 17 buffer chan net.Conn 18 done *done.Instance 19 } 20 21 func (l *OutboundListener) add(conn net.Conn) { 22 select { 23 case l.buffer <- conn: 24 case <-l.done.Wait(): 25 conn.Close() // nolint: errcheck 26 default: 27 conn.Close() // nolint: errcheck 28 } 29 } 30 31 // Accept implements net.Listener. 32 func (l *OutboundListener) Accept() (net.Conn, error) { 33 select { 34 case <-l.done.Wait(): 35 return nil, newError("listen closed") 36 case c := <-l.buffer: 37 return c, nil 38 } 39 } 40 41 // Close implement net.Listener. 42 func (l *OutboundListener) Close() error { 43 common.Must(l.done.Close()) 44 L: 45 for { 46 select { 47 case c := <-l.buffer: 48 c.Close() // nolint: errcheck 49 default: 50 break L 51 } 52 } 53 return nil 54 } 55 56 // Addr implements net.Listener. 57 func (l *OutboundListener) Addr() net.Addr { 58 return &net.TCPAddr{ 59 IP: net.IP{0, 0, 0, 0}, 60 Port: 0, 61 } 62 } 63 64 // Outbound is a outbound.Handler that handles gRPC connections. 65 type Outbound struct { 66 tag string 67 listener *OutboundListener 68 access sync.RWMutex 69 closed bool 70 } 71 72 // Dispatch implements outbound.Handler. 73 func (co *Outbound) Dispatch(ctx context.Context, link *transport.Link) { 74 co.access.RLock() 75 76 if co.closed { 77 common.Interrupt(link.Reader) 78 common.Interrupt(link.Writer) 79 co.access.RUnlock() 80 return 81 } 82 83 closeSignal := done.New() 84 c := net.NewConnection(net.ConnectionInputMulti(link.Writer), net.ConnectionOutputMulti(link.Reader), net.ConnectionOnClose(closeSignal)) 85 co.listener.add(c) 86 co.access.RUnlock() 87 <-closeSignal.Wait() 88 } 89 90 // Tag implements outbound.Handler. 91 func (co *Outbound) Tag() string { 92 return co.tag 93 } 94 95 // Start implements common.Runnable. 96 func (co *Outbound) Start() error { 97 co.access.Lock() 98 co.closed = false 99 co.access.Unlock() 100 return nil 101 } 102 103 // Close implements common.Closable. 104 func (co *Outbound) Close() error { 105 co.access.Lock() 106 defer co.access.Unlock() 107 108 co.closed = true 109 return co.listener.Close() 110 }