diff --git a/.golangci.yml b/.golangci.yml index 19bd0f5..70f5a22 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -30,6 +30,7 @@ linters: - gocognit - golint - goimports + - nosnakecase linters-settings: revive: @@ -41,4 +42,9 @@ linters-settings: disable: - composites - fieldalignment - - shadow \ No newline at end of file + - shadow + gci: + sections: + - standard + - prefix(github.com/sagernet/sing) + - default \ No newline at end of file diff --git a/common/bufio/cache.go b/common/bufio/cache.go index 94e7286..6cb057b 100644 --- a/common/bufio/cache.go +++ b/common/bufio/cache.go @@ -6,6 +6,8 @@ import ( "time" "github.com/sagernet/sing/common/buf" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" ) type CachedConn struct { @@ -135,3 +137,41 @@ func (r *CachedReader) Close() error { r.buffer.Release() return nil } + +type CachedPacketConn struct { + N.PacketConn + buffer *buf.Buffer + destination M.Socksaddr +} + +func NewCachedPacketConn(conn N.PacketConn, buffer *buf.Buffer, destination M.Socksaddr) *CachedPacketConn { + return &CachedPacketConn{ + PacketConn: conn, + buffer: buffer, + destination: destination, + } +} + +func (c *CachedPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { + if c.buffer != nil { + _, err = buffer.ReadFrom(c.buffer) + if err != nil { + return M.Socksaddr{}, err + } + c.buffer = nil + return c.destination, nil + } + return c.PacketConn.ReadPacket(buffer) +} + +func (c *CachedPacketConn) Upstream() any { + return c.PacketConn +} + +func (c *CachedPacketConn) ReaderReplaceable() bool { + return c.buffer == nil +} + +func (c *CachedPacketConn) WriterReplaceable() bool { + return true +}