add buffer size option for udp connection
This commit is contained in:
@@ -2,10 +2,10 @@ package v5
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"math"
|
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/common/bufpool"
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
)
|
)
|
||||||
@@ -28,14 +28,15 @@ type udpRelayConn struct {
|
|||||||
udpConn *net.UDPConn
|
udpConn *net.UDPConn
|
||||||
tcpConn net.Conn
|
tcpConn net.Conn
|
||||||
taddr net.Addr
|
taddr net.Addr
|
||||||
rbuf [math.MaxUint16]byte
|
bufferSize int
|
||||||
wbuf [math.MaxInt16]byte
|
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpRelayConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
func (c *udpRelayConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||||
buf := c.rbuf[:]
|
buf := bufpool.Get(c.bufferSize)
|
||||||
nn, err := c.udpConn.Read(buf[:])
|
defer bufpool.Put(buf)
|
||||||
|
|
||||||
|
nn, err := c.udpConn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -81,7 +82,8 @@ func (c *udpRelayConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|||||||
Data: b,
|
Data: b,
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := c.wbuf[:]
|
buf := bufpool.Get(c.bufferSize)
|
||||||
|
defer bufpool.Put(buf)
|
||||||
|
|
||||||
nn, err := dgram.WriteTo(bytes.NewBuffer(buf[:0]))
|
nn, err := dgram.WriteTo(bytes.NewBuffer(buf[:0]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ func (c *socks5Connector) relayUDP(ctx context.Context, conn net.Conn, addr net.
|
|||||||
udpConn: cc.(*net.UDPConn),
|
udpConn: cc.(*net.UDPConn),
|
||||||
tcpConn: conn,
|
tcpConn: conn,
|
||||||
taddr: addr,
|
taddr: addr,
|
||||||
|
bufferSize: c.md.udpBufferSize,
|
||||||
logger: log,
|
logger: log,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,15 @@ import (
|
|||||||
mdutil "github.com/go-gost/x/metadata/util"
|
mdutil "github.com/go-gost/x/metadata/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultUDPBufferSize = 4096
|
||||||
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
noTLS bool
|
noTLS bool
|
||||||
relay string
|
relay string
|
||||||
|
udpBufferSize int
|
||||||
udpTimeout time.Duration
|
udpTimeout time.Duration
|
||||||
muxCfg *mux.Config
|
muxCfg *mux.Config
|
||||||
}
|
}
|
||||||
@@ -20,6 +25,10 @@ func (c *socks5Connector) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
c.md.connectTimeout = mdutil.GetDuration(md, "timeout")
|
c.md.connectTimeout = mdutil.GetDuration(md, "timeout")
|
||||||
c.md.noTLS = mdutil.GetBool(md, "notls")
|
c.md.noTLS = mdutil.GetBool(md, "notls")
|
||||||
c.md.relay = mdutil.GetString(md, "relay")
|
c.md.relay = mdutil.GetString(md, "relay")
|
||||||
|
c.md.udpBufferSize = mdutil.GetInt(md, "udp.bufferSize", "udpBufferSize")
|
||||||
|
if c.md.udpBufferSize <= 0 {
|
||||||
|
c.md.udpBufferSize = defaultUDPBufferSize
|
||||||
|
}
|
||||||
c.md.udpTimeout = mdutil.GetDuration(md, "udp.timeout")
|
c.md.udpTimeout = mdutil.GetDuration(md, "udp.timeout")
|
||||||
|
|
||||||
c.md.muxCfg = &mux.Config{
|
c.md.muxCfg = &mux.Config{
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func (c *ssuConnector) Connect(ctx context.Context, conn net.Conn, network, addr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// standard UDP relay
|
// standard UDP relay
|
||||||
return ss.UDPClientConn(pc, conn.RemoteAddr(), taddr), nil
|
return ss.UDPClientConn(pc, conn.RemoteAddr(), taddr, c.md.udpBufferSize), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cipher != nil {
|
if c.cipher != nil {
|
||||||
|
|||||||
@@ -10,16 +10,13 @@ import (
|
|||||||
type metadata struct {
|
type metadata struct {
|
||||||
key string
|
key string
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
|
udpBufferSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ssuConnector) parseMetadata(md mdata.Metadata) (err error) {
|
func (c *ssuConnector) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
c.md.key = mdutil.GetString(md, "key")
|
||||||
key = "key"
|
c.md.connectTimeout = mdutil.GetDuration(md, "timeout", "connectTimeout")
|
||||||
connectTimeout = "timeout"
|
c.md.udpBufferSize = mdutil.GetInt(md, "udpBufferSize", "udp.bufferSize")
|
||||||
)
|
|
||||||
|
|
||||||
c.md.key = mdutil.GetString(md, key)
|
|
||||||
c.md.connectTimeout = mdutil.GetDuration(md, connectTimeout)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ type metadata struct {
|
|||||||
compression bool
|
compression bool
|
||||||
probeResistance *probeResistance
|
probeResistance *probeResistance
|
||||||
enableUDP bool
|
enableUDP bool
|
||||||
|
udpBufferSize int
|
||||||
header http.Header
|
header http.Header
|
||||||
hash string
|
hash string
|
||||||
authBasicRealm string
|
authBasicRealm string
|
||||||
@@ -77,6 +78,7 @@ func (h *httpHandler) parseMetadata(md mdata.Metadata) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
h.md.enableUDP = mdutil.GetBool(md, "udp")
|
h.md.enableUDP = mdutil.GetBool(md, "udp")
|
||||||
|
h.md.udpBufferSize = mdutil.GetInt(md, "udp.bufferSize", "udpBufferSize")
|
||||||
h.md.hash = mdutil.GetString(md, "hash")
|
h.md.hash = mdutil.GetString(md, "hash")
|
||||||
h.md.authBasicRealm = mdutil.GetString(md, "authBasicRealm")
|
h.md.authBasicRealm = mdutil.GetString(md, "authBasicRealm")
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ func (h *httpHandler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecorde
|
|||||||
|
|
||||||
relay := udp.NewRelay(socks.UDPTunServerConn(conn), pc).
|
relay := udp.NewRelay(socks.UDPTunServerConn(conn), pc).
|
||||||
WithBypass(h.options.Bypass).
|
WithBypass(h.options.Bypass).
|
||||||
|
WithBufferSize(h.md.udpBufferSize).
|
||||||
WithLogger(log)
|
WithLogger(log)
|
||||||
|
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ func (h *relayHandler) bindUDP(ctx context.Context, conn net.Conn, network, addr
|
|||||||
|
|
||||||
r := udp.NewRelay(relay_util.UDPTunServerConn(conn), pc).
|
r := udp.NewRelay(relay_util.UDPTunServerConn(conn), pc).
|
||||||
WithBypass(h.options.Bypass).
|
WithBypass(h.options.Bypass).
|
||||||
|
WithBufferSize(h.md.udpBufferSize).
|
||||||
WithLogger(log)
|
WithLogger(log)
|
||||||
|
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
readTimeout time.Duration
|
readTimeout time.Duration
|
||||||
|
udpBufferSize int
|
||||||
enableBind bool
|
enableBind bool
|
||||||
noDelay bool
|
noDelay bool
|
||||||
hash string
|
hash string
|
||||||
@@ -43,6 +44,7 @@ func (h *relayHandler) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
h.md.readTimeout = 15 * time.Second
|
h.md.readTimeout = 15 * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.md.udpBufferSize = mdutil.GetInt(md, "udp.bufferSize", "udpBufferSize")
|
||||||
h.md.enableBind = mdutil.GetBool(md, "bind")
|
h.md.enableBind = mdutil.GetBool(md, "bind")
|
||||||
h.md.noDelay = mdutil.GetBool(md, "nodelay")
|
h.md.noDelay = mdutil.GetBool(md, "nodelay")
|
||||||
h.md.hash = mdutil.GetString(md, "hash")
|
h.md.hash = mdutil.GetString(md, "hash")
|
||||||
|
|||||||
@@ -121,9 +121,11 @@ func (h *routerHandler) handleAssociate(ctx context.Context, conn net.Conn, netw
|
|||||||
|
|
||||||
log.Debugf("%s/%s: router=%s, connector=%s, weight=%d established", host, network, routerID, connectorID, connectorID.Weight())
|
log.Debugf("%s/%s: router=%s, connector=%s, weight=%d established", host, network, routerID, connectorID, connectorID.Weight())
|
||||||
|
|
||||||
var b [MaxMessageSize]byte
|
b := bufpool.Get(h.md.bufferSize)
|
||||||
|
defer bufpool.Put(b)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
n, err := conn.Read(b[:])
|
n, err := conn.Read(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -3,16 +3,18 @@ package router
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/common/bufpool"
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
"github.com/go-gost/relay"
|
"github.com/go-gost/relay"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *routerHandler) handleEntrypoint(log logger.Logger) error {
|
func (h *routerHandler) handleEntrypoint(log logger.Logger) error {
|
||||||
var buf [MaxMessageSize]byte
|
buf := bufpool.Get(h.md.bufferSize)
|
||||||
|
defer bufpool.Put(buf)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
n, addr, err := h.epConn.ReadFrom(buf[:])
|
n, addr, err := h.epConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/core/ingress"
|
"github.com/go-gost/core/ingress"
|
||||||
@@ -13,13 +12,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxMessageSize = math.MaxUint16
|
|
||||||
defaultTTL = 15 * time.Second
|
defaultTTL = 15 * time.Second
|
||||||
|
defaultBufferSize = 4096
|
||||||
defaultCacheExpiration = time.Second
|
defaultCacheExpiration = time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
readTimeout time.Duration
|
readTimeout time.Duration
|
||||||
|
bufferSize int
|
||||||
|
|
||||||
entryPoint string
|
entryPoint string
|
||||||
ingress ingress.Ingress
|
ingress ingress.Ingress
|
||||||
@@ -40,6 +40,10 @@ type metadata struct {
|
|||||||
|
|
||||||
func (h *routerHandler) parseMetadata(md mdata.Metadata) (err error) {
|
func (h *routerHandler) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
h.md.readTimeout = mdutil.GetDuration(md, "readTimeout")
|
h.md.readTimeout = mdutil.GetDuration(md, "readTimeout")
|
||||||
|
h.md.bufferSize = mdutil.GetInt(md, "router.bufferSize", "bufferSize")
|
||||||
|
if h.md.bufferSize <= 0 {
|
||||||
|
h.md.bufferSize = defaultBufferSize
|
||||||
|
}
|
||||||
|
|
||||||
h.md.entryPoint = mdutil.GetString(md, "entrypoint")
|
h.md.entryPoint = mdutil.GetString(md, "entrypoint")
|
||||||
h.md.ingress = registry.IngressRegistry().Get(mdutil.GetString(md, "ingress"))
|
h.md.ingress = registry.IngressRegistry().Get(mdutil.GetString(md, "ingress"))
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ func (h *socks5Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.WithFields(map[string]any{
|
log.WithFields(map[string]any{
|
||||||
|
"network": ro.Network,
|
||||||
"duration": time.Since(start),
|
"duration": time.Since(start),
|
||||||
"inputBytes": ro.InputBytes,
|
"inputBytes": ro.InputBytes,
|
||||||
"outputBytes": ro.OutputBytes,
|
"outputBytes": ro.OutputBytes,
|
||||||
@@ -186,7 +187,7 @@ func (h *socks5Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl
|
|||||||
return h.handleMuxBind(ctx, conn, "tcp", address, ro, log)
|
return h.handleMuxBind(ctx, conn, "tcp", address, ro, log)
|
||||||
case gosocks5.CmdUdp:
|
case gosocks5.CmdUdp:
|
||||||
ro.Network = "udp"
|
ro.Network = "udp"
|
||||||
return h.handleUDP(ctx, conn, ro, log)
|
return h.handleUDP(ctx, conn, "udp", ro, log)
|
||||||
case socks.CmdUDPTun:
|
case socks.CmdUDPTun:
|
||||||
ro.Network = "udp"
|
ro.Network = "udp"
|
||||||
return h.handleUDPTun(ctx, conn, "udp", address, ro, log)
|
return h.handleUDPTun(ctx, conn, "udp", address, ro, log)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type metadata struct {
|
|||||||
noTLS bool
|
noTLS bool
|
||||||
enableBind bool
|
enableBind bool
|
||||||
enableUDP bool
|
enableUDP bool
|
||||||
|
udpBufferSize int
|
||||||
compatibilityMode bool
|
compatibilityMode bool
|
||||||
hash string
|
hash string
|
||||||
muxCfg *mux.Config
|
muxCfg *mux.Config
|
||||||
@@ -50,6 +51,7 @@ func (h *socks5Handler) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
h.md.noTLS = mdutil.GetBool(md, "notls")
|
h.md.noTLS = mdutil.GetBool(md, "notls")
|
||||||
h.md.enableBind = mdutil.GetBool(md, "bind")
|
h.md.enableBind = mdutil.GetBool(md, "bind")
|
||||||
h.md.enableUDP = mdutil.GetBool(md, "udp")
|
h.md.enableUDP = mdutil.GetBool(md, "udp")
|
||||||
|
h.md.udpBufferSize = mdutil.GetInt(md, "udp.bufferSize", "udpBufferSize")
|
||||||
|
|
||||||
h.md.compatibilityMode = mdutil.GetBool(md, "comp")
|
h.md.compatibilityMode = mdutil.GetBool(md, "comp")
|
||||||
h.md.hash = mdutil.GetString(md, "hash")
|
h.md.hash = mdutil.GetString(md, "hash")
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ import (
|
|||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, network string, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||||
log = log.WithFields(map[string]any{
|
log = log.WithFields(map[string]any{
|
||||||
"cmd": "udp",
|
"network": network,
|
||||||
|
"cmd": network,
|
||||||
})
|
})
|
||||||
|
|
||||||
if !h.md.enableUDP {
|
if !h.md.enableUDP {
|
||||||
@@ -39,7 +40,7 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecor
|
|||||||
Netns: h.options.Netns,
|
Netns: h.options.Netns,
|
||||||
}
|
}
|
||||||
|
|
||||||
cc, err := lc.ListenPacket(ctx, "udp", "")
|
cc, err := lc.ListenPacket(ctx, network, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
reply := gosocks5.NewReply(gosocks5.Failure, nil)
|
reply := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
@@ -74,7 +75,7 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecor
|
|||||||
|
|
||||||
// obtain a udp connection
|
// obtain a udp connection
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
c, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "udp", "") // UDP association
|
c, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), network, "") // UDP association
|
||||||
ro.Route = buf.String()
|
ro.Route = buf.String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
@@ -106,7 +107,7 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecor
|
|||||||
string(clientID),
|
string(clientID),
|
||||||
limiter.ServiceOption(h.options.Service),
|
limiter.ServiceOption(h.options.Service),
|
||||||
limiter.ScopeOption(limiter.ScopeClient),
|
limiter.ScopeOption(limiter.ScopeClient),
|
||||||
limiter.NetworkOption("udp"),
|
limiter.NetworkOption(network),
|
||||||
limiter.ClientOption(string(clientID)),
|
limiter.ClientOption(string(clientID)),
|
||||||
limiter.SrcOption(conn.RemoteAddr().String()),
|
limiter.SrcOption(conn.RemoteAddr().String()),
|
||||||
)
|
)
|
||||||
@@ -119,8 +120,9 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r := udp.NewRelay(socks.UDPConn(cc), pc).
|
r := udp.NewRelay(socks.UDPConn(cc, h.md.udpBufferSize), pc).
|
||||||
WithBypass(h.options.Bypass).
|
WithBypass(h.options.Bypass).
|
||||||
|
WithBufferSize(h.md.udpBufferSize).
|
||||||
WithLogger(log)
|
WithLogger(log)
|
||||||
|
|
||||||
go r.Run(ctx)
|
go r.Run(ctx)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network, address string, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network, address string, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||||
log = log.WithFields(map[string]any{
|
log = log.WithFields(map[string]any{
|
||||||
|
"network": network,
|
||||||
"cmd": "udp-tun",
|
"cmd": "udp-tun",
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network
|
|||||||
|
|
||||||
// obtain a udp connection
|
// obtain a udp connection
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
c, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "udp", "") // UDP association
|
c, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), network, "") // UDP association
|
||||||
ro.Route = buf.String()
|
ro.Route = buf.String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
@@ -94,7 +95,7 @@ func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network
|
|||||||
Netns: h.options.Netns,
|
Netns: h.options.Netns,
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
pc, err = lc.ListenPacket(ctx, "udp", bindAddr.String())
|
pc, err = lc.ListenPacket(ctx, network, bindAddr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
reply := gosocks5.NewReply(gosocks5.Failure, nil)
|
reply := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
@@ -133,6 +134,7 @@ func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network
|
|||||||
|
|
||||||
r := udp.NewRelay(socks.UDPTunServerConn(conn), pc).
|
r := udp.NewRelay(socks.UDPTunServerConn(conn), pc).
|
||||||
WithBypass(h.options.Bypass).
|
WithBypass(h.options.Bypass).
|
||||||
|
WithBufferSize(h.md.udpBufferSize).
|
||||||
WithLogger(log)
|
WithLogger(log)
|
||||||
|
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/common/bufpool"
|
||||||
"github.com/go-gost/core/handler"
|
"github.com/go-gost/core/handler"
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
@@ -112,7 +113,7 @@ func (h *ssuHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
|
|||||||
pc = h.cipher.PacketConn(pc)
|
pc = h.cipher.PacketConn(pc)
|
||||||
}
|
}
|
||||||
// standard UDP relay.
|
// standard UDP relay.
|
||||||
pc = ss.UDPServerConn(pc, conn.RemoteAddr())
|
pc = ss.UDPServerConn(pc, conn.RemoteAddr(), h.md.udpBufferSize)
|
||||||
} else {
|
} else {
|
||||||
if h.cipher != nil {
|
if h.cipher != nil {
|
||||||
conn = ss.ShadowConn(h.cipher.StreamConn(conn), nil)
|
conn = ss.ShadowConn(h.cipher.StreamConn(conn), nil)
|
||||||
@@ -150,11 +151,18 @@ func (h *ssuHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
|
|||||||
func (h *ssuHandler) relayPacket(ctx context.Context, pc1, pc2 net.PacketConn, ro *xrecorder.HandlerRecorderObject, log logger.Logger) (err error) {
|
func (h *ssuHandler) relayPacket(ctx context.Context, pc1, pc2 net.PacketConn, ro *xrecorder.HandlerRecorderObject, log logger.Logger) (err error) {
|
||||||
errc := make(chan error, 2)
|
errc := make(chan error, 2)
|
||||||
|
|
||||||
|
bufferSize := h.md.udpBufferSize
|
||||||
|
if bufferSize <= 0 {
|
||||||
|
bufferSize = defaultBufferSize
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
var b [MaxMessageSize]byte
|
b := bufpool.Get(bufferSize)
|
||||||
|
defer bufpool.Put(b)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
n, addr, err := pc1.ReadFrom(b[:])
|
n, addr, err := pc1.ReadFrom(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -185,10 +193,12 @@ func (h *ssuHandler) relayPacket(ctx context.Context, pc1, pc2 net.PacketConn, r
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
var b [MaxMessageSize]byte
|
b := bufpool.Get(bufferSize)
|
||||||
|
defer bufpool.Put(b)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
n, raddr, err := pc2.ReadFrom(b[:])
|
n, raddr, err := pc2.ReadFrom(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package ss
|
package ss
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/core/metadata"
|
mdata "github.com/go-gost/core/metadata"
|
||||||
@@ -9,22 +8,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxMessageSize = math.MaxUint16
|
defaultBufferSize = 4096
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
key string
|
key string
|
||||||
readTimeout time.Duration
|
readTimeout time.Duration
|
||||||
|
udpBufferSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ssuHandler) parseMetadata(md mdata.Metadata) (err error) {
|
func (h *ssuHandler) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
|
||||||
key = "key"
|
|
||||||
readTimeout = "readTimeout"
|
|
||||||
)
|
|
||||||
|
|
||||||
h.md.key = mdutil.GetString(md, key)
|
h.md.key = mdutil.GetString(md, "key")
|
||||||
h.md.readTimeout = mdutil.GetDuration(md, readTimeout)
|
h.md.readTimeout = mdutil.GetDuration(md, "readTimeout")
|
||||||
|
h.md.udpBufferSize = mdutil.GetInt(md, "udpBufferSize", "udp.bufferSize")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,13 @@ import (
|
|||||||
mdutil "github.com/go-gost/x/metadata/util"
|
mdutil "github.com/go-gost/x/metadata/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultBufferSize = 4096
|
||||||
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
udpTimeout time.Duration
|
udpTimeout time.Duration
|
||||||
|
udpBufferSize int
|
||||||
|
|
||||||
sniffing bool
|
sniffing bool
|
||||||
sniffingUDP bool
|
sniffingUDP bool
|
||||||
@@ -34,6 +39,7 @@ type metadata struct {
|
|||||||
|
|
||||||
func (h *tungoHandler) parseMetadata(md mdata.Metadata) (err error) {
|
func (h *tungoHandler) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
h.md.udpTimeout = mdutil.GetDuration(md, "udpTimeout", "tungo.udpTimeout")
|
h.md.udpTimeout = mdutil.GetDuration(md, "udpTimeout", "tungo.udpTimeout")
|
||||||
|
h.md.udpBufferSize = mdutil.GetInt(md, "udp.bufferSize", "udpBufferSize")
|
||||||
|
|
||||||
h.md.sniffing = mdutil.GetBool(md, "sniffing")
|
h.md.sniffing = mdutil.GetBool(md, "sniffing")
|
||||||
h.md.sniffingUDP = mdutil.GetBool(md, "sniffing.udp")
|
h.md.sniffingUDP = mdutil.GetBool(md, "sniffing.udp")
|
||||||
|
|||||||
+21
-7
@@ -6,13 +6,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/common/bufpool"
|
||||||
"github.com/go-gost/core/handler"
|
"github.com/go-gost/core/handler"
|
||||||
"github.com/go-gost/core/observer/stats"
|
"github.com/go-gost/core/observer/stats"
|
||||||
"github.com/go-gost/core/recorder"
|
"github.com/go-gost/core/recorder"
|
||||||
@@ -45,6 +45,7 @@ type transportHandler struct {
|
|||||||
|
|
||||||
// UDP session timeout.
|
// UDP session timeout.
|
||||||
udpTimeout time.Duration
|
udpTimeout time.Duration
|
||||||
|
udpBufferSize int
|
||||||
|
|
||||||
sniffing bool
|
sniffing bool
|
||||||
sniffingUDP bool
|
sniffingUDP bool
|
||||||
@@ -344,33 +345,46 @@ func (h *transportHandler) handleUDPConn(uc adapter.UDPConn) {
|
|||||||
|
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
log.Infof("%s <-> %s", remoteAddr, dstAddr)
|
log.Infof("%s <-> %s", remoteAddr, dstAddr)
|
||||||
pipePacketData(conn, cc, h.sniffingUDP, ro, h.udpTimeout)
|
h.pipePacketData(conn, cc, ro)
|
||||||
log.WithFields(map[string]any{
|
log.WithFields(map[string]any{
|
||||||
"duration": time.Since(t),
|
"duration": time.Since(t),
|
||||||
}).Infof("%s >-< %s", remoteAddr, dstAddr)
|
}).Infof("%s >-< %s", remoteAddr, dstAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func pipePacketData(conn1, conn2 net.Conn, sniffing bool, ro *xrecorder.HandlerRecorderObject, timeout time.Duration) {
|
func (h *transportHandler) pipePacketData(conn1, conn2 net.Conn, ro *xrecorder.HandlerRecorderObject) {
|
||||||
|
timeout := h.udpTimeout
|
||||||
if timeout <= 0 {
|
if timeout <= 0 {
|
||||||
timeout = udpSessionTimeout
|
timeout = udpSessionTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bufferSize := h.udpBufferSize
|
||||||
|
if bufferSize <= 0 {
|
||||||
|
bufferSize = defaultBufferSize
|
||||||
|
}
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
copyPacketData(conn1, conn2, sniffing, false, ro, timeout)
|
|
||||||
|
buf := bufpool.Get(bufferSize)
|
||||||
|
defer bufpool.Put(buf)
|
||||||
|
|
||||||
|
copyPacketData(conn1, conn2, buf, h.sniffing, false, ro, timeout)
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
copyPacketData(conn2, conn1, sniffing, true, ro, timeout)
|
|
||||||
|
buf := bufpool.Get(bufferSize)
|
||||||
|
defer bufpool.Put(buf)
|
||||||
|
|
||||||
|
copyPacketData(conn2, conn1, buf, h.sniffing, true, ro, timeout)
|
||||||
}()
|
}()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyPacketData(dst, src net.Conn, sniffing bool, c2s bool, ro *xrecorder.HandlerRecorderObject, timeout time.Duration) error {
|
func copyPacketData(dst, src net.Conn, buf []byte, sniffing bool, c2s bool, ro *xrecorder.HandlerRecorderObject, timeout time.Duration) error {
|
||||||
buf := make([]byte, math.MaxUint16/2)
|
|
||||||
isDNS := false
|
isDNS := false
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|||||||
@@ -176,6 +176,8 @@ func (c *conn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|||||||
if !c.keepalive {
|
if !c.keepalive {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
}
|
}
|
||||||
|
c.SetIdle(false)
|
||||||
|
|
||||||
return c.PacketConn.WriteTo(b, addr)
|
return c.PacketConn.WriteTo(b, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,6 +214,10 @@ func (c *conn) RemoteAddr() net.Addr {
|
|||||||
return c.remoteAddr
|
return c.remoteAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *conn) SetReadDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *conn) IsIdle() bool {
|
func (c *conn) IsIdle() bool {
|
||||||
return atomic.LoadInt32(&c.idle) > 0
|
return atomic.LoadInt32(&c.idle) > 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,21 @@ package udp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math"
|
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/go-gost/core/bypass"
|
"github.com/go-gost/core/bypass"
|
||||||
|
"github.com/go-gost/core/common/bufpool"
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxMessageSize = math.MaxUint16
|
defaultBufferSize = 4096
|
||||||
)
|
)
|
||||||
|
|
||||||
type Relay struct {
|
type Relay struct {
|
||||||
pc1 net.PacketConn
|
pc1 net.PacketConn
|
||||||
pc2 net.PacketConn
|
pc2 net.PacketConn
|
||||||
|
bufferSize int
|
||||||
bypass bypass.Bypass
|
bypass bypass.Bypass
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
@@ -38,14 +38,26 @@ func (r *Relay) WithLogger(logger logger.Logger) *Relay {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Relay) WithBufferSize(n int) *Relay {
|
||||||
|
r.bufferSize = n
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Relay) Run(ctx context.Context) (err error) {
|
func (r *Relay) Run(ctx context.Context) (err error) {
|
||||||
errc := make(chan error, 2)
|
errc := make(chan error, 2)
|
||||||
|
|
||||||
|
bufferSize := r.bufferSize
|
||||||
|
if bufferSize <= 0 {
|
||||||
|
bufferSize = defaultBufferSize
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
var b [MaxMessageSize]byte
|
b := bufpool.Get(bufferSize)
|
||||||
|
defer bufpool.Put(b)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
n, raddr, err := r.pc1.ReadFrom(b[:])
|
n, raddr, err := r.pc1.ReadFrom(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -64,7 +76,6 @@ func (r *Relay) Run(ctx context.Context) (err error) {
|
|||||||
if r.logger != nil {
|
if r.logger != nil {
|
||||||
r.logger.Tracef("%s >>> %s data: %d",
|
r.logger.Tracef("%s >>> %s data: %d",
|
||||||
r.pc2.LocalAddr(), raddr, n)
|
r.pc2.LocalAddr(), raddr, n)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -78,10 +89,12 @@ func (r *Relay) Run(ctx context.Context) (err error) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
var b [MaxMessageSize]byte
|
b := bufpool.Get(bufferSize)
|
||||||
|
defer bufpool.Put(b)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
n, raddr, err := r.pc2.ReadFrom(b[:])
|
n, raddr, err := r.pc2.ReadFrom(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -100,7 +113,6 @@ func (r *Relay) Run(ctx context.Context) (err error) {
|
|||||||
if r.logger != nil {
|
if r.logger != nil {
|
||||||
r.logger.Tracef("%s <<< %s data: %d",
|
r.logger.Tracef("%s <<< %s data: %d",
|
||||||
r.pc2.LocalAddr(), raddr, n)
|
r.pc2.LocalAddr(), raddr, n)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package relay
|
package relay
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/go-gost/core/common/bufpool"
|
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
"github.com/go-gost/relay"
|
"github.com/go-gost/relay"
|
||||||
)
|
)
|
||||||
@@ -108,89 +106,3 @@ func (c *udpTunConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|||||||
func (c *udpTunConn) Write(b []byte) (n int, err error) {
|
func (c *udpTunConn) Write(b []byte) (n int, err error) {
|
||||||
return c.WriteTo(b, c.taddr)
|
return c.WriteTo(b, c.taddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
DefaultBufferSize = 4096
|
|
||||||
)
|
|
||||||
|
|
||||||
type udpConn struct {
|
|
||||||
net.PacketConn
|
|
||||||
raddr net.Addr
|
|
||||||
taddr net.Addr
|
|
||||||
bufferSize int
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPConn(c net.PacketConn, bufferSize int) net.PacketConn {
|
|
||||||
return &udpConn{
|
|
||||||
PacketConn: c,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadFrom reads an UDP datagram.
|
|
||||||
// NOTE: for server side,
|
|
||||||
// the returned addr is the target address the client want to relay to.
|
|
||||||
func (c *udpConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|
||||||
rbuf := bufpool.Get(c.bufferSize)
|
|
||||||
defer bufpool.Put(rbuf)
|
|
||||||
|
|
||||||
n, c.raddr, err = c.PacketConn.ReadFrom(rbuf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
socksAddr := gosocks5.Addr{}
|
|
||||||
header := gosocks5.UDPHeader{
|
|
||||||
Addr: &socksAddr,
|
|
||||||
}
|
|
||||||
hlen, err := header.ReadFrom(bytes.NewReader(rbuf[:n]))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n = copy(b, rbuf[hlen:n])
|
|
||||||
|
|
||||||
addr, err = net.ResolveUDPAddr("udp", socksAddr.String())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) Read(b []byte) (n int, err error) {
|
|
||||||
n, _, err = c.ReadFrom(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|
||||||
wbuf := bufpool.Get(c.bufferSize)
|
|
||||||
defer bufpool.Put(wbuf)
|
|
||||||
|
|
||||||
socksAddr := gosocks5.Addr{}
|
|
||||||
if err = socksAddr.ParseFrom(addr.String()); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
header := gosocks5.UDPHeader{
|
|
||||||
Addr: &socksAddr,
|
|
||||||
}
|
|
||||||
dgram := gosocks5.UDPDatagram{
|
|
||||||
Header: &header,
|
|
||||||
Data: b,
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := bytes.NewBuffer(wbuf[:0])
|
|
||||||
_, err = dgram.WriteTo(buf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = c.PacketConn.WriteTo(buf.Bytes(), c.raddr)
|
|
||||||
n = len(b)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) Write(b []byte) (n int, err error) {
|
|
||||||
return c.WriteTo(b, c.taddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) RemoteAddr() net.Addr {
|
|
||||||
return c.raddr
|
|
||||||
}
|
|
||||||
|
|||||||
+19
-12
@@ -2,9 +2,9 @@ package socks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"math"
|
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/common/bufpool"
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -86,18 +86,23 @@ func (c *udpTunConn) Write(b []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxMessageSize = math.MaxUint16
|
defaultBufferSize = 4096
|
||||||
)
|
)
|
||||||
|
|
||||||
type udpConn struct {
|
type udpConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
raddr net.Addr
|
raddr net.Addr
|
||||||
taddr net.Addr
|
taddr net.Addr
|
||||||
|
bufferSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func UDPConn(c net.PacketConn) net.PacketConn {
|
func UDPConn(c net.PacketConn, bufferSize int) net.PacketConn {
|
||||||
|
if bufferSize <= 0 {
|
||||||
|
bufferSize = defaultBufferSize
|
||||||
|
}
|
||||||
return &udpConn{
|
return &udpConn{
|
||||||
PacketConn: c,
|
PacketConn: c,
|
||||||
|
bufferSize: bufferSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,9 +110,10 @@ func UDPConn(c net.PacketConn) net.PacketConn {
|
|||||||
// NOTE: for server side,
|
// NOTE: for server side,
|
||||||
// the returned addr is the target address the client want to relay to.
|
// the returned addr is the target address the client want to relay to.
|
||||||
func (c *udpConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
func (c *udpConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||||
var rbuf [MaxMessageSize]byte
|
buf := bufpool.Get(c.bufferSize)
|
||||||
|
defer bufpool.Put(buf)
|
||||||
|
|
||||||
n, c.raddr, err = c.PacketConn.ReadFrom(rbuf[:])
|
n, c.raddr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -116,11 +122,11 @@ func (c *udpConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|||||||
header := gosocks5.UDPHeader{
|
header := gosocks5.UDPHeader{
|
||||||
Addr: &socksAddr,
|
Addr: &socksAddr,
|
||||||
}
|
}
|
||||||
hlen, err := header.ReadFrom(bytes.NewReader(rbuf[:n]))
|
hlen, err := header.ReadFrom(bytes.NewReader(buf[:n]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n = copy(b, rbuf[hlen:n])
|
n = copy(b, buf[hlen:n])
|
||||||
|
|
||||||
addr, err = net.ResolveUDPAddr("udp", socksAddr.String())
|
addr, err = net.ResolveUDPAddr("udp", socksAddr.String())
|
||||||
return
|
return
|
||||||
@@ -132,7 +138,6 @@ func (c *udpConn) Read(b []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
func (c *udpConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
||||||
|
|
||||||
socksAddr := gosocks5.Addr{}
|
socksAddr := gosocks5.Addr{}
|
||||||
if err = socksAddr.ParseFrom(addr.String()); err != nil {
|
if err = socksAddr.ParseFrom(addr.String()); err != nil {
|
||||||
return
|
return
|
||||||
@@ -146,14 +151,16 @@ func (c *udpConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|||||||
Data: b,
|
Data: b,
|
||||||
}
|
}
|
||||||
|
|
||||||
var wbuf [MaxMessageSize]byte
|
buf := bufpool.Get(c.bufferSize)
|
||||||
buf := bytes.NewBuffer(wbuf[:][:0])
|
defer bufpool.Put(buf)
|
||||||
_, err = dgram.WriteTo(buf)
|
|
||||||
|
bw := bytes.NewBuffer(buf[:0])
|
||||||
|
_, err = dgram.WriteTo(bw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.PacketConn.WriteTo(buf.Bytes(), c.raddr)
|
_, err = c.PacketConn.WriteTo(bw.Bytes(), c.raddr)
|
||||||
n = len(b)
|
n = len(b)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
+26
-13
@@ -2,14 +2,14 @@ package ss
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"math"
|
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/common/bufpool"
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxMessageSize = math.MaxUint16
|
defaultBufferSize = 4096
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -21,38 +21,50 @@ type UDPConn struct {
|
|||||||
net.PacketConn
|
net.PacketConn
|
||||||
raddr net.Addr
|
raddr net.Addr
|
||||||
taddr net.Addr
|
taddr net.Addr
|
||||||
|
bufferSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func UDPClientConn(c net.PacketConn, remoteAddr, targetAddr net.Addr) *UDPConn {
|
func UDPClientConn(c net.PacketConn, remoteAddr, targetAddr net.Addr, bufferSize int) *UDPConn {
|
||||||
|
if bufferSize <= 0 {
|
||||||
|
bufferSize = defaultBufferSize
|
||||||
|
}
|
||||||
|
|
||||||
return &UDPConn{
|
return &UDPConn{
|
||||||
PacketConn: c,
|
PacketConn: c,
|
||||||
raddr: remoteAddr,
|
raddr: remoteAddr,
|
||||||
taddr: targetAddr,
|
taddr: targetAddr,
|
||||||
|
bufferSize: bufferSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func UDPServerConn(c net.PacketConn, remoteAddr net.Addr) *UDPConn {
|
func UDPServerConn(c net.PacketConn, remoteAddr net.Addr, bufferSize int) *UDPConn {
|
||||||
|
if bufferSize <= 0 {
|
||||||
|
bufferSize = defaultBufferSize
|
||||||
|
}
|
||||||
|
|
||||||
return &UDPConn{
|
return &UDPConn{
|
||||||
PacketConn: c,
|
PacketConn: c,
|
||||||
raddr: remoteAddr,
|
raddr: remoteAddr,
|
||||||
|
bufferSize: bufferSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *UDPConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
func (c *UDPConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||||
var rbuf [MaxMessageSize]byte
|
buf := bufpool.Get(c.bufferSize)
|
||||||
|
defer bufpool.Put(buf)
|
||||||
|
|
||||||
n, _, err = c.PacketConn.ReadFrom(rbuf[:])
|
n, _, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
saddr := gosocks5.Addr{}
|
saddr := gosocks5.Addr{}
|
||||||
addrLen, err := saddr.ReadFrom(bytes.NewReader(rbuf[:n]))
|
addrLen, err := saddr.ReadFrom(bytes.NewReader(buf[:n]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n = copy(b, rbuf[addrLen:n])
|
n = copy(b, buf[addrLen:n])
|
||||||
addr, err = net.ResolveUDPAddr("udp", saddr.String())
|
addr, err = net.ResolveUDPAddr("udp", saddr.String())
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -64,20 +76,21 @@ func (c *UDPConn) Read(b []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *UDPConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
func (c *UDPConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
||||||
var wbuf [MaxMessageSize]byte
|
|
||||||
|
|
||||||
socksAddr := gosocks5.Addr{}
|
socksAddr := gosocks5.Addr{}
|
||||||
if err = socksAddr.ParseFrom(addr.String()); err != nil {
|
if err = socksAddr.ParseFrom(addr.String()); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
addrLen, err := socksAddr.Encode(wbuf[:])
|
buf := bufpool.Get(c.bufferSize)
|
||||||
|
defer bufpool.Put(buf)
|
||||||
|
|
||||||
|
addrLen, err := socksAddr.Encode(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n = copy(wbuf[addrLen:], b)
|
n = copy(buf[addrLen:], b)
|
||||||
_, err = c.PacketConn.WriteTo(wbuf[:addrLen+n], c.raddr)
|
_, err = c.PacketConn.WriteTo(buf[:addrLen+n], c.raddr)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
defaultTTL = 5 * time.Second
|
defaultTTL = 5 * time.Second
|
||||||
defaultReadBufferSize = 8192
|
defaultReadBufferSize = 4096
|
||||||
defaultReadQueueSize = 128
|
defaultReadQueueSize = 128
|
||||||
defaultBacklog = 128
|
defaultBacklog = 128
|
||||||
)
|
)
|
||||||
@@ -23,33 +23,25 @@ type metadata struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *udpListener) parseMetadata(md mdata.Metadata) (err error) {
|
func (l *udpListener) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
l.md.backlog = mdutil.GetInt(md, "backlog")
|
||||||
readBufferSize = "readBufferSize"
|
if l.md.backlog <= 0 {
|
||||||
readQueueSize = "readQueueSize"
|
l.md.backlog = defaultBacklog
|
||||||
backlog = "backlog"
|
}
|
||||||
keepalive = "keepalive"
|
|
||||||
ttl = "ttl"
|
|
||||||
)
|
|
||||||
|
|
||||||
l.md.ttl = mdutil.GetDuration(md, ttl)
|
l.md.keepalive = mdutil.GetBool(md, "keepalive")
|
||||||
|
l.md.ttl = mdutil.GetDuration(md, "ttl", "keepalive.ttl")
|
||||||
if l.md.ttl <= 0 {
|
if l.md.ttl <= 0 {
|
||||||
l.md.ttl = defaultTTL
|
l.md.ttl = defaultTTL
|
||||||
}
|
}
|
||||||
l.md.readBufferSize = mdutil.GetInt(md, readBufferSize)
|
l.md.readBufferSize = mdutil.GetInt(md, "readBufferSize", "udp.bufferSize")
|
||||||
if l.md.readBufferSize <= 0 {
|
if l.md.readBufferSize <= 0 {
|
||||||
l.md.readBufferSize = defaultReadBufferSize
|
l.md.readBufferSize = defaultReadBufferSize
|
||||||
}
|
}
|
||||||
|
|
||||||
l.md.readQueueSize = mdutil.GetInt(md, readQueueSize)
|
l.md.readQueueSize = mdutil.GetInt(md, "readQueueSize", "recvQueueSize")
|
||||||
if l.md.readQueueSize <= 0 {
|
if l.md.readQueueSize <= 0 {
|
||||||
l.md.readQueueSize = defaultReadQueueSize
|
l.md.readQueueSize = defaultReadQueueSize
|
||||||
}
|
}
|
||||||
|
|
||||||
l.md.backlog = mdutil.GetInt(md, backlog)
|
|
||||||
if l.md.backlog <= 0 {
|
|
||||||
l.md.backlog = defaultBacklog
|
|
||||||
}
|
|
||||||
l.md.keepalive = mdutil.GetBool(md, keepalive)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user