From 3b4e77c4c1b3283b8453b2e25bdfac4f55ae68bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 30 Jul 2022 09:51:11 +0800 Subject: [PATCH] Improve error processing --- go.mod | 4 +-- go.sum | 8 +++--- gvisor.go | 6 ++--- gvisor_err.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ gvisor_udp.go | 5 ++-- 5 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 gvisor_err.go diff --git a/go.mod b/go.mod index 3130f46..eb929b1 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/sagernet/sing-tun go 1.18 require ( - github.com/sagernet/sing v0.0.0-20220726034811-bc109486f14e + github.com/sagernet/sing v0.0.0-20220729120910-4376f188c512 github.com/vishvananda/netlink v1.1.0 - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 gvisor.dev/gvisor v0.0.0-20220711011657-cecae2f4234d ) diff --git a/go.sum b/go.sum index 9d3cc31..9767470 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/sagernet/sing v0.0.0-20220726034811-bc109486f14e h1:5lfrAc+vSv0iW6eHGNLyHC+a/k6BDGJvYxYxwB/68Kk= -github.com/sagernet/sing v0.0.0-20220726034811-bc109486f14e/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM= +github.com/sagernet/sing v0.0.0-20220729120910-4376f188c512 h1:dCWDE55LpZu//W02FccNbGObZFlv1N2NS0yUdf2i4Mc= +github.com/sagernet/sing v0.0.0-20220729120910-4376f188c512/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM= github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= @@ -9,8 +9,8 @@ github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695AP github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= gvisor.dev/gvisor v0.0.0-20220711011657-cecae2f4234d h1:KjI6i6P1ib9DiNdNIN8pb2TXfBewpKHf3O58cjj9vw4= diff --git a/gvisor.go b/gvisor.go index a1e4d39..5962a60 100644 --- a/gvisor.go +++ b/gvisor.go @@ -70,7 +70,7 @@ func (t *GVisorTun) Start() error { }) tErr := ipStack.CreateNIC(defaultNIC, linkEndpoint) if tErr != nil { - return E.New("create nic: ", tErr) + return E.New("create nic: ", wrapStackError(tErr)) } ipStack.SetRouteTable([]tcpip.Route{ {Destination: header.IPv4EmptySubnet, NIC: defaultNIC}, @@ -118,7 +118,7 @@ func (t *GVisorTun) Start() error { var metadata M.Metadata metadata.Source = M.SocksaddrFromNet(lAddr) metadata.Destination = M.SocksaddrFromNet(rAddr) - hErr := t.handler.NewConnection(t.ctx, tcpConn, metadata) + hErr := t.handler.NewConnection(t.ctx, &gTCPConn{tcpConn}, metadata) if hErr != nil { endpoint.Abort() } @@ -143,7 +143,7 @@ func (t *GVisorTun) Start() error { var metadata M.Metadata metadata.Source = M.SocksaddrFromNet(lAddr) metadata.Destination = M.SocksaddrFromNet(rAddr) - hErr := t.handler.NewPacketConnection(ContextWithNeedTimeout(t.ctx, true), bufio.NewPacketConn(&bufio.UnbindPacketConn{ExtendedConn: bufio.NewExtendedConn(udpConn), Addr: M.SocksaddrFromNet(rAddr)}), metadata) + hErr := t.handler.NewPacketConnection(ContextWithNeedTimeout(t.ctx, true), bufio.NewPacketConn(&bufio.UnbindPacketConn{ExtendedConn: bufio.NewExtendedConn(&gUDPConn{udpConn}), Addr: M.SocksaddrFromNet(rAddr)}), metadata) if hErr != nil { endpoint.Abort() } diff --git a/gvisor_err.go b/gvisor_err.go new file mode 100644 index 0000000..99b7a3e --- /dev/null +++ b/gvisor_err.go @@ -0,0 +1,69 @@ +package tun + +import ( + "net" + + "gvisor.dev/gvisor/pkg/tcpip" + "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" +) + +type gTCPConn struct { + *gonet.TCPConn +} + +func (c *gTCPConn) Upstream() any { + return c.TCPConn +} + +func (c *gTCPConn) Write(b []byte) (n int, err error) { + n, err = c.TCPConn.Write(b) + if err == nil { + return + } + err = wrapError(err) + return +} + +type gUDPConn struct { + *gonet.UDPConn +} + +func (c *gUDPConn) Read(b []byte) (n int, err error) { + n, err = c.UDPConn.Read(b) + if err == nil { + return + } + err = wrapError(err) + return +} + +func (c *gUDPConn) Write(b []byte) (n int, err error) { + n, err = c.UDPConn.Write(b) + if err == nil { + return + } + err = wrapError(err) + return +} + +func wrapStackError(err tcpip.Error) error { + switch err.(type) { + case *tcpip.ErrClosedForSend: + return net.ErrClosed + case *tcpip.ErrClosedForReceive: + return net.ErrClosed + } + return wrapStackError(err) +} + +func wrapError(err error) error { + if opErr, isOpErr := err.(*net.OpError); isOpErr { + switch opErr.Err.Error() { + case "endpoint is closed for send": + return net.ErrClosed + case "endpoint is closed for receive": + return net.ErrClosed + } + } + return err +} diff --git a/gvisor_udp.go b/gvisor_udp.go index ddfd11a..0d1ea84 100644 --- a/gvisor_udp.go +++ b/gvisor_udp.go @@ -7,7 +7,6 @@ import ( "net/netip" "github.com/sagernet/sing/common/buf" - E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/udpnat" @@ -75,7 +74,7 @@ func (w *UDPBackWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) false, ) if err != nil { - return E.New(err) + return wrapStackError(err) } defer route.Release() @@ -113,7 +112,7 @@ func (w *UDPBackWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) if err != nil { route.Stats().UDP.PacketSendErrors.Increment() - return E.New(err) + return wrapStackError(err) } route.Stats().UDP.PacketsSent.Increment()