mirror of https://github.com/v2ray/v2ray-core
replace channel with pipe in udp conn
parent
f3feec8acf
commit
91109f3657
|
@ -2,7 +2,6 @@ package inbound
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
@ -20,6 +19,7 @@ import (
|
|||
"v2ray.com/core/transport/internet"
|
||||
"v2ray.com/core/transport/internet/tcp"
|
||||
"v2ray.com/core/transport/internet/udp"
|
||||
"v2ray.com/core/transport/pipe"
|
||||
)
|
||||
|
||||
type worker interface {
|
||||
|
@ -121,7 +121,8 @@ func (w *tcpWorker) Port() net.Port {
|
|||
|
||||
type udpConn struct {
|
||||
lastActivityTime int64 // in seconds
|
||||
input chan *buf.Buffer
|
||||
reader buf.Reader
|
||||
writer buf.Writer
|
||||
output func([]byte) (int, error)
|
||||
remote net.Addr
|
||||
local net.Addr
|
||||
|
@ -136,52 +137,21 @@ func (c *udpConn) updateActivity() {
|
|||
|
||||
// ReadMultiBuffer implements buf.Reader
|
||||
func (c *udpConn) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
var payload buf.MultiBuffer
|
||||
|
||||
select {
|
||||
case in := <-c.input:
|
||||
payload.Append(in)
|
||||
default:
|
||||
select {
|
||||
case in := <-c.input:
|
||||
payload.Append(in)
|
||||
case <-c.done.Wait():
|
||||
return nil, io.EOF
|
||||
}
|
||||
mb, err := c.reader.ReadMultiBuffer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
L:
|
||||
for {
|
||||
select {
|
||||
case in := <-c.input:
|
||||
payload.Append(in)
|
||||
default:
|
||||
break L
|
||||
}
|
||||
}
|
||||
|
||||
c.updateActivity()
|
||||
|
||||
if c.uplink != nil {
|
||||
c.uplink.Add(int64(payload.Len()))
|
||||
c.uplink.Add(int64(mb.Len()))
|
||||
}
|
||||
|
||||
return payload, nil
|
||||
return mb, nil
|
||||
}
|
||||
|
||||
func (c *udpConn) Read(buf []byte) (int, error) {
|
||||
select {
|
||||
case in := <-c.input:
|
||||
defer in.Release()
|
||||
c.updateActivity()
|
||||
nBytes := copy(buf, in.Bytes())
|
||||
if c.uplink != nil {
|
||||
c.uplink.Add(int64(nBytes))
|
||||
}
|
||||
return nBytes, nil
|
||||
case <-c.done.Wait():
|
||||
return 0, io.EOF
|
||||
}
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// Write implements io.Writer.
|
||||
|
@ -198,6 +168,7 @@ func (c *udpConn) Write(buf []byte) (int, error) {
|
|||
|
||||
func (c *udpConn) Close() error {
|
||||
common.Must(c.done.Close())
|
||||
common.Must(common.Close(c.writer))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -251,8 +222,10 @@ func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
|
|||
return conn, true
|
||||
}
|
||||
|
||||
pReader, pWriter := pipe.New(pipe.DiscardOverflow(), pipe.WithSizeLimit(16*1024))
|
||||
conn := &udpConn{
|
||||
input: make(chan *buf.Buffer, 32),
|
||||
reader: pReader,
|
||||
writer: pWriter,
|
||||
output: func(b []byte) (int, error) {
|
||||
return w.hub.WriteTo(b, id.src)
|
||||
},
|
||||
|
@ -282,13 +255,9 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
|||
id.dest = originalDest
|
||||
}
|
||||
conn, existing := w.getConnection(id)
|
||||
select {
|
||||
case conn.input <- b:
|
||||
case <-conn.done.Wait():
|
||||
b.Release()
|
||||
default:
|
||||
b.Release()
|
||||
}
|
||||
|
||||
// payload will be discarded in pipe is full.
|
||||
conn.writer.WriteMultiBuffer(buf.NewMultiBufferValue(b)) // nolint: errcheck
|
||||
|
||||
if !existing {
|
||||
common.Must(w.checker.Start())
|
||||
|
|
|
@ -22,12 +22,13 @@ const (
|
|||
|
||||
type pipe struct {
|
||||
sync.Mutex
|
||||
data buf.MultiBuffer
|
||||
readSignal *signal.Notifier
|
||||
writeSignal *signal.Notifier
|
||||
done *done.Instance
|
||||
limit int32
|
||||
state state
|
||||
data buf.MultiBuffer
|
||||
readSignal *signal.Notifier
|
||||
writeSignal *signal.Notifier
|
||||
done *done.Instance
|
||||
limit int32
|
||||
state state
|
||||
discardOverflow bool
|
||||
}
|
||||
|
||||
var errBufferFull = errors.New("buffer full")
|
||||
|
@ -121,10 +122,14 @@ func (p *pipe) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||
|
||||
for {
|
||||
err := p.writeMultiBufferInternal(mb)
|
||||
if err == nil {
|
||||
switch {
|
||||
case err == nil:
|
||||
p.readSignal.Signal()
|
||||
return nil
|
||||
} else if err != errBufferFull {
|
||||
case err == errBufferFull && p.discardOverflow:
|
||||
mb.Release()
|
||||
return nil
|
||||
case err != errBufferFull:
|
||||
mb.Release()
|
||||
p.readSignal.Signal()
|
||||
return err
|
||||
|
|
|
@ -11,18 +11,28 @@ import (
|
|||
// Option for creating new Pipes.
|
||||
type Option func(*pipe)
|
||||
|
||||
// WithoutSizeLimit returns an Option for Pipe to have no size limit.
|
||||
func WithoutSizeLimit() Option {
|
||||
return func(p *pipe) {
|
||||
p.limit = -1
|
||||
}
|
||||
}
|
||||
|
||||
// WithSizeLimit returns an Option for Pipe to have the given size limit.
|
||||
func WithSizeLimit(limit int32) Option {
|
||||
return func(p *pipe) {
|
||||
p.limit = limit
|
||||
}
|
||||
}
|
||||
|
||||
// DiscardOverflow returns an Option for Pipe to discard writes if full.
|
||||
func DiscardOverflow() Option {
|
||||
return func(p *pipe) {
|
||||
p.discardOverflow = true
|
||||
}
|
||||
}
|
||||
|
||||
// OptionsFromContext returns a list of Options from context.
|
||||
func OptionsFromContext(ctx context.Context) []Option {
|
||||
var opt []Option
|
||||
|
||||
|
|
Loading…
Reference in New Issue