1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-09 17:30:44 +00:00
v2fly/app/commander/outbound.go

110 lines
2.1 KiB
Go
Raw Normal View History

2018-02-05 22:38:24 +00:00
package commander
import (
"context"
2018-02-08 14:39:46 +00:00
"sync"
2018-02-05 22:38:24 +00:00
2018-04-04 19:32:40 +00:00
"v2ray.com/core/common"
2018-04-16 22:31:10 +00:00
"v2ray.com/core/common/net"
2018-05-27 12:42:53 +00:00
"v2ray.com/core/common/signal/done"
"v2ray.com/core/common/vio"
2018-04-16 22:31:10 +00:00
"v2ray.com/core/transport/pipe"
2018-02-05 22:38:24 +00:00
)
2018-04-14 11:09:58 +00:00
// OutboundListener is a net.Listener for listening gRPC connections.
2018-02-05 22:38:24 +00:00
type OutboundListener struct {
buffer chan net.Conn
2018-05-27 12:42:53 +00:00
done *done.Instance
2018-02-05 22:38:24 +00:00
}
func (l *OutboundListener) add(conn net.Conn) {
select {
case l.buffer <- conn:
2018-04-15 18:40:47 +00:00
case <-l.done.Wait():
2018-05-25 22:47:51 +00:00
conn.Close() // nolint: errcheck
2018-02-05 22:38:24 +00:00
default:
2018-05-25 22:47:51 +00:00
conn.Close() // nolint: errcheck
2018-02-05 22:38:24 +00:00
}
}
2018-04-04 19:32:40 +00:00
// Accept implements net.Listener.
2018-02-05 22:38:24 +00:00
func (l *OutboundListener) Accept() (net.Conn, error) {
2018-02-08 22:37:47 +00:00
select {
2018-04-15 18:40:47 +00:00
case <-l.done.Wait():
2018-03-15 02:32:10 +00:00
return nil, newError("listen closed")
2018-02-08 22:37:47 +00:00
case c := <-l.buffer:
return c, nil
2018-02-05 22:38:24 +00:00
}
}
2018-04-04 19:32:40 +00:00
// Close implement net.Listener.
2018-02-05 22:38:24 +00:00
func (l *OutboundListener) Close() error {
2018-04-04 19:32:40 +00:00
common.Must(l.done.Close())
2018-02-08 22:37:47 +00:00
L:
for {
select {
case c := <-l.buffer:
2018-05-25 22:47:51 +00:00
c.Close() // nolint: errcheck
2018-02-08 22:37:47 +00:00
default:
break L
}
}
2018-02-05 22:38:24 +00:00
return nil
}
2018-04-04 19:32:40 +00:00
// Addr implements net.Listener.
2018-02-05 22:38:24 +00:00
func (l *OutboundListener) Addr() net.Addr {
return &net.TCPAddr{
IP: net.IP{0, 0, 0, 0},
Port: 0,
}
}
// Outbound is a outbound.Handler that handles gRPC connections.
2018-04-04 19:32:40 +00:00
type Outbound struct {
2018-02-05 22:38:24 +00:00
tag string
listener *OutboundListener
2018-02-08 14:39:46 +00:00
access sync.RWMutex
closed bool
2018-02-05 22:38:24 +00:00
}
// Dispatch implements outbound.Handler.
func (co *Outbound) Dispatch(ctx context.Context, link *vio.Link) {
2018-02-08 14:39:46 +00:00
co.access.RLock()
if co.closed {
2018-04-16 22:31:10 +00:00
pipe.CloseError(link.Reader)
pipe.CloseError(link.Writer)
2018-02-08 14:39:46 +00:00
co.access.RUnlock()
return
}
2018-06-09 02:29:40 +00:00
closeSignal := done.New()
c := net.NewConnection(net.ConnectionInputMulti(link.Writer), net.ConnectionOutputMulti(link.Reader), net.ConnectionOnClose(closeSignal))
2018-02-05 22:38:24 +00:00
co.listener.add(c)
2018-02-08 14:39:46 +00:00
co.access.RUnlock()
2018-02-05 22:38:24 +00:00
<-closeSignal.Wait()
}
// Tag implements outbound.Handler.
2018-04-04 19:32:40 +00:00
func (co *Outbound) Tag() string {
2018-02-05 22:38:24 +00:00
return co.tag
}
2018-04-03 22:57:44 +00:00
// Start implements common.Runnable.
2018-04-04 19:32:40 +00:00
func (co *Outbound) Start() error {
2018-02-08 14:39:46 +00:00
co.access.Lock()
co.closed = false
co.access.Unlock()
2018-02-05 22:38:24 +00:00
return nil
}
2018-04-03 22:57:44 +00:00
// Close implements common.Closable.
2018-04-04 19:32:40 +00:00
func (co *Outbound) Close() error {
2018-02-08 14:39:46 +00:00
co.access.Lock()
2018-04-04 19:32:40 +00:00
defer co.access.Unlock()
2018-02-08 14:39:46 +00:00
2018-04-04 19:32:40 +00:00
co.closed = true
return co.listener.Close()
2018-02-08 14:39:46 +00:00
}