mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-04 04:17:38 +03:00
Deprecate stack buffer
This commit is contained in:
parent
d852e9c03d
commit
c68251b6d0
18 changed files with 28 additions and 399 deletions
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
|
@ -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")
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
|
@ -1,5 +0,0 @@
|
|||
//go:build disable_unsafe_buffer
|
||||
|
||||
package common
|
||||
|
||||
const UnsafeBuffer = false
|
|
@ -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))
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue