From f4910823a65158fbb9cce69c1747c2bf1b4e3880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 28 Oct 2023 20:59:48 +0800 Subject: [PATCH 1/5] Add unidirectional NATPacketConn --- common/bufio/nat.go | 63 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/common/bufio/nat.go b/common/bufio/nat.go index d652094..43e8d40 100644 --- a/common/bufio/nat.go +++ b/common/bufio/nat.go @@ -9,21 +9,62 @@ import ( N "github.com/sagernet/sing/common/network" ) -type NATPacketConn struct { +type NATPacketConn interface { N.NetPacketConn - origin M.Socksaddr - destination M.Socksaddr + UpdateDestination(destinationAddress netip.Addr) } -func NewNATPacketConn(conn N.NetPacketConn, origin M.Socksaddr, destination M.Socksaddr) *NATPacketConn { - return &NATPacketConn{ +func NewUnidirectionalNATPacketConn(conn N.NetPacketConn, origin M.Socksaddr, destination M.Socksaddr) NATPacketConn { + return &unidirectionalNATPacketConn{ NetPacketConn: conn, origin: origin, destination: destination, } } -func (c *NATPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { +func NewNATPacketConn(conn N.NetPacketConn, origin M.Socksaddr, destination M.Socksaddr) NATPacketConn { + return &bidirectionalNATPacketConn{ + NetPacketConn: conn, + origin: origin, + destination: destination, + } +} + +type unidirectionalNATPacketConn struct { + N.NetPacketConn + origin M.Socksaddr + destination M.Socksaddr +} + +func (c *unidirectionalNATPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { + if M.SocksaddrFromNet(addr) == c.destination { + addr = c.origin.UDPAddr() + } + return c.NetPacketConn.WriteTo(p, addr) +} + +func (c *unidirectionalNATPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { + if destination == c.destination { + destination = c.origin + } + return c.NetPacketConn.WritePacket(buffer, destination) +} + +func (c *unidirectionalNATPacketConn) UpdateDestination(destinationAddress netip.Addr) { + c.destination = M.SocksaddrFrom(destinationAddress, c.destination.Port) +} + +func (c *unidirectionalNATPacketConn) Upstream() any { + return c.NetPacketConn +} + +type bidirectionalNATPacketConn struct { + N.NetPacketConn + origin M.Socksaddr + destination M.Socksaddr +} + +func (c *bidirectionalNATPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { n, addr, err = c.NetPacketConn.ReadFrom(p) if err == nil && M.SocksaddrFromNet(addr) == c.origin { addr = c.destination.UDPAddr() @@ -31,14 +72,14 @@ func (c *NATPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { return } -func (c *NATPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { +func (c *bidirectionalNATPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { if M.SocksaddrFromNet(addr) == c.destination { addr = c.origin.UDPAddr() } return c.NetPacketConn.WriteTo(p, addr) } -func (c *NATPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { +func (c *bidirectionalNATPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { destination, err = c.NetPacketConn.ReadPacket(buffer) if destination == c.origin { destination = c.destination @@ -46,17 +87,17 @@ func (c *NATPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, return } -func (c *NATPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { +func (c *bidirectionalNATPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { if destination == c.destination { destination = c.origin } return c.NetPacketConn.WritePacket(buffer, destination) } -func (c *NATPacketConn) UpdateDestination(destinationAddress netip.Addr) { +func (c *bidirectionalNATPacketConn) UpdateDestination(destinationAddress netip.Addr) { c.destination = M.SocksaddrFrom(destinationAddress, c.destination.Port) } -func (c *NATPacketConn) Upstream() any { +func (c *bidirectionalNATPacketConn) Upstream() any { return c.NetPacketConn } From 875ad36cc6d11a2da66d4c6bc1aecb1109fc237d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Wed, 8 Nov 2023 11:29:54 +0800 Subject: [PATCH 2/5] Add common.Top func --- common/upstream.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/common/upstream.go b/common/upstream.go index 30070cc..6aeea4f 100644 --- a/common/upstream.go +++ b/common/upstream.go @@ -22,3 +22,10 @@ func MustCast[T any](obj any) T { } return value } + +func Top(obj any) any { + if u, ok := obj.(WithUpstream); ok { + return Top(u.Upstream()) + } + return obj +} From 4fbbd193203c315866f013c31f065e87dcb13d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 8 Oct 2023 12:00:00 +0800 Subject: [PATCH 3/5] Add `NetConn() net.Conn` support for cast --- common/upstream.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/common/upstream.go b/common/upstream.go index 6aeea4f..9af3604 100644 --- a/common/upstream.go +++ b/common/upstream.go @@ -1,9 +1,15 @@ package common +import "net" + type WithUpstream interface { Upstream() any } +type stdWithUpstreamNetConn interface { + NetConn() net.Conn +} + func Cast[T any](obj any) (T, bool) { if c, ok := obj.(T); ok { return c, true @@ -11,6 +17,9 @@ func Cast[T any](obj any) (T, bool) { if u, ok := obj.(WithUpstream); ok { return Cast[T](u.Upstream()) } + if u, ok := obj.(stdWithUpstreamNetConn); ok { + return Cast[T](u.NetConn()) + } return DefaultValue[T](), false } @@ -27,5 +36,8 @@ func Top(obj any) any { if u, ok := obj.(WithUpstream); ok { return Top(u.Upstream()) } + if u, ok := obj.(stdWithUpstreamNetConn); ok { + return Top(u.NetConn()) + } return obj } From 256fafcd99b62121362acbe1a17f56bced557f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Fri, 17 Nov 2023 23:08:00 +0800 Subject: [PATCH 4/5] Add filemanager.chown --- service/filemanager/default.go | 7 +++++++ service/filemanager/manager.go | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/service/filemanager/default.go b/service/filemanager/default.go index f7b984e..b77c086 100644 --- a/service/filemanager/default.go +++ b/service/filemanager/default.go @@ -93,6 +93,13 @@ func (m *defaultManager) CreateTemp(pattern string) (*os.File, error) { return file, nil } +func (m *defaultManager) Chown(path string) error { + if m.chown { + return os.Chown(path, m.userID, m.groupID) + } + return nil +} + func (m *defaultManager) Mkdir(path string, perm os.FileMode) error { path = m.BasePath(path) err := os.Mkdir(path, perm) diff --git a/service/filemanager/manager.go b/service/filemanager/manager.go index 6367146..2de9a6c 100644 --- a/service/filemanager/manager.go +++ b/service/filemanager/manager.go @@ -12,6 +12,7 @@ type Manager interface { OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) Create(name string) (*os.File, error) CreateTemp(pattern string) (*os.File, error) + Chown(name string) error Mkdir(path string, perm os.FileMode) error MkdirAll(path string, perm os.FileMode) error Remove(path string) error @@ -50,6 +51,14 @@ func CreateTemp(ctx context.Context, pattern string) (*os.File, error) { return manager.CreateTemp(pattern) } +func Chown(ctx context.Context, name string) error { + manager := service.FromContext[Manager](ctx) + if manager == nil { + return nil + } + return manager.Chown(name) +} + func Mkdir(ctx context.Context, path string, perm os.FileMode) error { manager := service.FromContext[Manager](ctx) if manager == nil { From 0457413904ff4420c6ef4ca90c18ebd0ab2a0555 Mon Sep 17 00:00:00 2001 From: H1JK Date: Fri, 19 May 2023 20:16:40 +0800 Subject: [PATCH 5/5] Add UoT read waiter support --- common/bufio/copy_direct_posix.go | 1 - common/uot/conn.go | 33 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/common/bufio/copy_direct_posix.go b/common/bufio/copy_direct_posix.go index 3501e66..07e535c 100644 --- a/common/bufio/copy_direct_posix.go +++ b/common/bufio/copy_direct_posix.go @@ -212,7 +212,6 @@ func (w *syscallPacketReadWaiter) InitializeReadWaiter(newBuffer func() *buf.Buf buffer.Truncate(readN) } else { buffer.Release() - buffer = nil } if w.readErr == syscall.EAGAIN { return false diff --git a/common/uot/conn.go b/common/uot/conn.go index fd7d898..b8e26ee 100644 --- a/common/uot/conn.go +++ b/common/uot/conn.go @@ -13,11 +13,17 @@ import ( N "github.com/sagernet/sing/common/network" ) +var ( + _ N.NetPacketConn = (*Conn)(nil) + _ N.PacketReadWaiter = (*Conn)(nil) +) + type Conn struct { net.Conn isConnect bool destination M.Socksaddr writer N.VectorisedWriter + newBuffer func() *buf.Buffer } func NewConn(conn net.Conn, request Request) *Conn { @@ -141,6 +147,33 @@ func (c *Conn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { return c.writer.WriteVectorised([]*buf.Buffer{header, buffer}) } +func (c *Conn) InitializeReadWaiter(newBuffer func() *buf.Buffer) { + c.newBuffer = newBuffer +} + +func (c *Conn) WaitReadPacket() (destination M.Socksaddr, err error) { + if c.isConnect { + destination = c.destination + } else { + destination, err = AddrParser.ReadAddrPort(c.Conn) + if err != nil { + return + } + } + var length uint16 + err = binary.Read(c.Conn, binary.BigEndian, &length) + if err != nil { + return + } + buffer := c.newBuffer() + _, err = buffer.ReadFullFrom(c.Conn, int(length)) + if err != nil { + buffer.Release() + return M.Socksaddr{}, E.Cause(err, "UoT read") + } + return +} + func (c *Conn) NeedAdditionalReadDeadline() bool { return true }