|
|
|
@ -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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
L:
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case in := <-c.input:
|
|
|
|
|
payload.Append(in)
|
|
|
|
|
default:
|
|
|
|
|
break L
|
|
|
|
|
}
|
|
|
|
|
mb, err := c.reader.ReadMultiBuffer()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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())
|
|
|
|
|