Deprecate stack buffer

This commit is contained in:
世界 2023-07-03 08:21:04 +08:00
parent d852e9c03d
commit c68251b6d0
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
18 changed files with 28 additions and 399 deletions

View file

@ -54,41 +54,19 @@ func NewSize(size int) *Buffer {
}
}
// Deprecated: use New instead.
func StackNew() *Buffer {
if common.UnsafeBuffer {
return &Buffer{
data: make([]byte, BufferSize),
start: ReversedHeader,
end: ReversedHeader,
}
} else {
return New()
}
return New()
}
// Deprecated: use NewPacket instead.
func StackNewPacket() *Buffer {
if common.UnsafeBuffer {
return &Buffer{
data: make([]byte, UDPBufferSize),
start: ReversedHeader,
end: ReversedHeader,
}
} else {
return NewPacket()
}
return NewPacket()
}
// Deprecated: use NewSize instead.
func StackNewSize(size int) *Buffer {
if size == 0 {
return &Buffer{}
}
if common.UnsafeBuffer {
return &Buffer{
data: Make(size),
}
} else {
return NewSize(size)
}
return NewSize(size)
}
func As(data []byte) *Buffer {

View file

@ -1,9 +0,0 @@
package buf
import "encoding/hex"
func EncodeHexString(src []byte) string {
dst := Make(hex.EncodedLen(len(src)))
hex.Encode(dst, src)
return string(dst)
}

View file

@ -11,46 +11,7 @@ func Put(buf []byte) error {
return DefaultAllocator.Put(buf)
}
// Deprecated: use array instead.
func Make(size int) []byte {
if size == 0 {
return nil
}
var buffer []byte
switch {
case size <= 2:
buffer = make([]byte, 2)
case size <= 4:
buffer = make([]byte, 4)
case size <= 8:
buffer = make([]byte, 8)
case size <= 16:
buffer = make([]byte, 16)
case size <= 32:
buffer = make([]byte, 32)
case size <= 64:
buffer = make([]byte, 64)
case size <= 128:
buffer = make([]byte, 128)
case size <= 256:
buffer = make([]byte, 256)
case size <= 512:
buffer = make([]byte, 512)
case size <= 1024:
buffer = make([]byte, 1024)
case size <= 2048:
buffer = make([]byte, 2048)
case size <= 4096:
buffer = make([]byte, 4096)
case size <= 8192:
buffer = make([]byte, 8192)
case size <= 16384:
buffer = make([]byte, 16384)
case size <= 32768:
buffer = make([]byte, 32768)
case size <= 65535:
buffer = make([]byte, 65535)
default:
return make([]byte, size)
}
return buffer[:size]
return make([]byte, size)
}

View file

@ -1,34 +0,0 @@
//go:build !disable_unsafe && go1.21
package buf
import (
"unsafe"
"github.com/sagernet/sing/common"
)
type dbgVar struct {
name string
value *int32
}
//go:linkname dbgvars runtime.dbgvars
var dbgvars any
// go.info.runtime.dbgvars: relocation target go.info.[]github.com/sagernet/sing/common/buf.dbgVar not defined
// var dbgvars []dbgVar
func init() {
if !common.UnsafeBuffer {
return
}
debugVars := *(*[]*dbgVar)(unsafe.Pointer(&dbgvars))
for _, v := range debugVars {
if v.name == "invalidptr" {
*v.value = 0
return
}
}
panic("can't disable invalidptr")
}

View file

@ -1,34 +0,0 @@
//go:build !disable_unsafe && !go1.21
package buf
import (
"unsafe"
"github.com/sagernet/sing/common"
)
type dbgVar struct {
name string
value *int32
}
//go:linkname dbgvars runtime.dbgvars
var dbgvars any
// go.info.runtime.dbgvars: relocation target go.info.[]github.com/sagernet/sing/common/buf.dbgVar not defined
// var dbgvars []dbgVar
func init() {
if !common.UnsafeBuffer {
return
}
debugVars := *(*[]dbgVar)(unsafe.Pointer(&dbgvars))
for _, v := range debugVars {
if v.name == "invalidptr" {
*v.value = 0
return
}
}
panic("can't disable invalidptr")
}

View file

@ -71,20 +71,7 @@ func CopyExtended(originDestination io.Writer, destination N.ExtendedWriter, sou
return
}
}
if !common.UnsafeBuffer || N.IsUnsafeWriter(destination) {
return CopyExtendedWithPool(originDestination, destination, source, readCounters, writeCounters)
}
bufferSize := N.CalculateMTU(source, destination)
if bufferSize > 0 {
bufferSize += headroom
} else {
bufferSize = buf.BufferSize
}
_buffer := buf.StackNewSize(bufferSize)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
return CopyExtendedBuffer(originDestination, destination, source, buffer, readCounters, writeCounters)
return CopyExtendedWithPool(originDestination, destination, source, readCounters, writeCounters)
}
func CopyExtendedBuffer(originDestination io.Writer, destination N.ExtendedWriter, source N.ExtendedReader, buffer *buf.Buffer, readCounters []N.CountFunc, writeCounters []N.CountFunc) (n int64, err error) {
@ -291,49 +278,7 @@ func CopyPacket(destinationConn N.PacketWriter, source N.PacketReader) (n int64,
return
}
}
if N.IsUnsafeWriter(destinationConn) {
return CopyPacketWithPool(destinationConn, source, readCounters, writeCounters)
}
bufferSize := N.CalculateMTU(source, destinationConn)
if bufferSize > 0 {
bufferSize += headroom
} else {
bufferSize = buf.UDPBufferSize
}
_buffer := buf.StackNewSize(bufferSize)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
buffer.IncRef()
defer buffer.DecRef()
var destination M.Socksaddr
var notFirstTime bool
readBufferRaw := buffer.Slice()
readBuffer := buf.With(readBufferRaw[:len(readBufferRaw)-rearHeadroom])
for {
readBuffer.Resize(frontHeadroom, 0)
destination, err = source.ReadPacket(readBuffer)
if err != nil {
if !notFirstTime {
err = N.HandshakeFailure(destinationConn, err)
}
return
}
dataLen := readBuffer.Len()
buffer.Resize(readBuffer.Start(), dataLen)
err = destinationConn.WritePacket(buffer, destination)
if err != nil {
return
}
n += int64(dataLen)
for _, counter := range readCounters {
counter(int64(dataLen))
}
for _, counter := range writeCounters {
counter(int64(dataLen))
}
notFirstTime = true
}
return CopyPacketWithPool(destinationConn, source, readCounters, writeCounters)
}
func CopyPacketWithSrcBuffer(destinationConn N.PacketWriter, source N.ThreadSafePacketReader, readCounters []N.CountFunc, writeCounters []N.CountFunc) (n int64, err error) {

View file

@ -1,127 +0,0 @@
package bufio
import (
"io"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
N "github.com/sagernet/sing/common/network"
)
func CopyTimes(dst io.Writer, src io.Reader, times int) (n int64, err error) {
return CopyExtendedTimes(NewExtendedWriter(N.UnwrapWriter(dst)), NewExtendedReader(N.UnwrapReader(src)), times)
}
func CopyExtendedTimes(dst N.ExtendedWriter, src N.ExtendedReader, times int) (n int64, err error) {
frontHeadroom := N.CalculateFrontHeadroom(dst)
rearHeadroom := N.CalculateRearHeadroom(dst)
bufferSize := N.CalculateMTU(src, dst)
if bufferSize > 0 {
bufferSize += frontHeadroom + rearHeadroom
} else {
bufferSize = buf.BufferSize
}
dstUnsafe := N.IsUnsafeWriter(dst)
var buffer *buf.Buffer
if !dstUnsafe {
_buffer := buf.StackNewSize(bufferSize)
defer common.KeepAlive(_buffer)
buffer = common.Dup(_buffer)
defer buffer.Release()
buffer.IncRef()
defer buffer.DecRef()
}
notFirstTime := true
for i := 0; i < times; i++ {
if dstUnsafe {
buffer = buf.NewSize(bufferSize)
}
readBufferRaw := buffer.Slice()
readBuffer := buf.With(readBufferRaw[:cap(readBufferRaw)-rearHeadroom])
readBuffer.Resize(frontHeadroom, 0)
err = src.ReadBuffer(readBuffer)
if err != nil {
buffer.Release()
if !notFirstTime {
err = N.HandshakeFailure(dst, err)
}
return
}
dataLen := readBuffer.Len()
buffer.Resize(readBuffer.Start(), dataLen)
err = dst.WriteBuffer(buffer)
if err != nil {
buffer.Release()
return
}
n += int64(dataLen)
notFirstTime = true
}
return
}
type ReadFromWriter interface {
io.ReaderFrom
io.Writer
}
func ReadFrom0(readerFrom ReadFromWriter, reader io.Reader) (n int64, err error) {
n, err = CopyTimes(readerFrom, reader, 1)
if err != nil {
return
}
var rn int64
rn, err = readerFrom.ReadFrom(reader)
if err != nil {
return
}
n += rn
return
}
func ReadFromN(readerFrom ReadFromWriter, reader io.Reader, times int) (n int64, err error) {
n, err = CopyTimes(readerFrom, reader, times)
if err != nil {
return
}
var rn int64
rn, err = readerFrom.ReadFrom(reader)
if err != nil {
return
}
n += rn
return
}
type WriteToReader interface {
io.WriterTo
io.Reader
}
func WriteTo0(writerTo WriteToReader, writer io.Writer) (n int64, err error) {
n, err = CopyTimes(writer, writerTo, 1)
if err != nil {
return
}
var wn int64
wn, err = writerTo.WriteTo(writer)
if err != nil {
return
}
n += wn
return
}
func WriteToN(writerTo WriteToReader, writer io.Writer, times int) (n int64, err error) {
n, err = CopyTimes(writer, writerTo, times)
if err != nil {
return
}
var wn int64
wn, err = writerTo.WriteTo(writer)
if err != nil {
return
}
n += wn
return
}

View file

@ -74,9 +74,7 @@ func (w *BufferedVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error
if bufferLen > 65535 {
bufferBytes = make([]byte, bufferLen)
} else {
_buffer := buf.StackNewSize(bufferLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(bufferLen)
defer buffer.Release()
bufferBytes = buffer.FreeBytes()
}

View file

@ -159,20 +159,14 @@ func IndexIndexed[T any](arr []T, block func(index int, it T) bool) int {
//go:norace
func Dup[T any](obj T) T {
if UnsafeBuffer {
pointer := uintptr(unsafe.Pointer(&obj))
//nolint:staticcheck
//goland:noinspection GoVetUnsafePointer
return *(*T)(unsafe.Pointer(pointer))
} else {
return obj
}
pointer := uintptr(unsafe.Pointer(&obj))
//nolint:staticcheck
//goland:noinspection GoVetUnsafePointer
return *(*T)(unsafe.Pointer(pointer))
}
func KeepAlive(obj any) {
if UnsafeBuffer {
runtime.KeepAlive(obj)
}
runtime.KeepAlive(obj)
}
func Uniq[T comparable](arr []T) []T {

View file

@ -6,9 +6,6 @@ type causeError struct {
}
func (e *causeError) Error() string {
if e.cause == nil {
return e.message
}
return e.message + ": " + e.cause.Error()
}

View file

@ -1,10 +0,0 @@
//go:build !unsafe_buffer && !disable_unsafe_buffer
package common
import "runtime"
// net/*Conn in windows keeps the buffer pointer passed in during io operations, so we disable it by default.
// https://github.com/golang/go/blob/4068be56ce7721a3d75606ea986d11e9ca27077a/src/internal/poll/fd_windows.go#L876
const UnsafeBuffer = runtime.GOOS != "windows"

View file

@ -1,5 +0,0 @@
//go:build disable_unsafe_buffer
package common
const UnsafeBuffer = false

View file

@ -75,9 +75,7 @@ func (c *Conn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if c.writer == nil {
bufferLen += len(p)
}
_buffer := buf.StackNewSize(bufferLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(bufferLen)
defer buffer.Release()
if !c.isConnect {
common.Must(AddrParser.WriteAddrPort(buffer, destination))
@ -124,9 +122,7 @@ func (c *Conn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
if c.writer == nil {
headerLen += buffer.Len()
}
_header := buf.StackNewSize(headerLen)
defer common.KeepAlive(_header)
header := common.Dup(_header)
header := buf.NewSize(headerLen)
defer header.Release()
if !c.isConnect {
common.Must(AddrParser.WriteAddrPort(header, destination))

View file

@ -5,7 +5,6 @@ import (
"io"
"net"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
M "github.com/sagernet/sing/common/metadata"
)
@ -53,9 +52,7 @@ func (c *ServerConn) loopInput() {
c.isConnect = request.IsConnect
c.destination = request.Destination
}
_buffer := buf.StackNew()
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewPacket()
defer buffer.Release()
for {
var destination M.Socksaddr
@ -95,9 +92,7 @@ func (c *ServerConn) loopInput() {
//warn:unsafe
func (c *ServerConn) loopOutput() {
_buffer := buf.StackNew()
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewPacket()
defer buffer.Release()
for {
buffer.FullReset()

View file

@ -64,9 +64,7 @@ func (c *AssociatePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err erro
//warn:unsafe
func (c *AssociatePacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
destination := M.SocksaddrFromNet(addr)
_buffer := buf.StackNewSize(3 + M.SocksaddrSerializer.AddrPortLen(destination) + len(p))
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(3 + M.SocksaddrSerializer.AddrPortLen(destination) + len(p))
defer buffer.Release()
common.Must(buffer.WriteZeroN(3))
err = M.SocksaddrSerializer.WriteAddrPort(buffer, destination)

View file

@ -40,9 +40,7 @@ func NewVectorisedAssociateConn(conn net.Conn, writer N.VectorisedWriter, remote
}
func (v *VectorisedAssociatePacketConn) WriteVectorisedPacket(buffers []*buf.Buffer, destination M.Socksaddr) error {
_header := buf.StackNewSize(3 + M.SocksaddrSerializer.AddrPortLen(destination))
defer common.KeepAlive(_header)
header := common.Dup(_header)
header := buf.NewSize(3 + M.SocksaddrSerializer.AddrPortLen(destination))
defer header.Release()
common.Must(header.WriteZeroN(3))
common.Must(M.SocksaddrSerializer.WriteAddrPort(header, destination))

View file

@ -85,9 +85,7 @@ func WriteRequest(writer io.Writer, request Request) error {
requestLen += len(request.Username)
}
_buffer := buf.StackNewSize(requestLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(requestLen)
defer buffer.Release()
common.Must(
@ -145,9 +143,7 @@ func ReadResponse(reader io.Reader) (response Response, err error) {
}
func WriteResponse(writer io.Writer, response Response) error {
_buffer := buf.StackNewSize(8)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(8)
defer buffer.Release()
common.Must(
buffer.WriteByte(0),

View file

@ -48,9 +48,7 @@ type AuthRequest struct {
}
func WriteAuthRequest(writer io.Writer, request AuthRequest) error {
_buffer := buf.StackNewSize(len(request.Methods) + 2)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(len(request.Methods) + 2)
defer buffer.Release()
common.Must(
buffer.WriteByte(Version),
@ -120,9 +118,7 @@ type UsernamePasswordAuthRequest struct {
}
func WriteUsernamePasswordAuthRequest(writer io.Writer, request UsernamePasswordAuthRequest) error {
_buffer := buf.StackNewSize(3 + len(request.Username) + len(request.Password))
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(3 + len(request.Username) + len(request.Password))
defer buffer.Release()
common.Must(
buffer.WriteByte(1),
@ -191,9 +187,7 @@ type Request struct {
}
func WriteRequest(writer io.Writer, request Request) error {
_buffer := buf.StackNewSize(3 + M.SocksaddrSerializer.AddrPortLen(request.Destination))
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(3 + M.SocksaddrSerializer.AddrPortLen(request.Destination))
defer buffer.Release()
common.Must(
buffer.WriteByte(Version),
@ -244,9 +238,7 @@ func WriteResponse(writer io.Writer, response Response) error {
bind.Addr = netip.IPv4Unspecified()
}
_buffer := buf.StackNewSize(3 + M.SocksaddrSerializer.AddrPortLen(bind))
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(3 + M.SocksaddrSerializer.AddrPortLen(bind))
defer buffer.Release()
common.Must(
buffer.WriteByte(Version),