mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-04 20:37:40 +03:00
Add vectorised interface
This commit is contained in:
parent
13f394e202
commit
05f9836bff
12 changed files with 371 additions and 13 deletions
|
@ -321,6 +321,12 @@ func (b *Buffer) Release() {
|
||||||
*b = Buffer{closed: true}
|
*b = Buffer{closed: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReleaseMulti(buffers []*Buffer) {
|
||||||
|
for _, buffer := range buffers {
|
||||||
|
buffer.Release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Buffer) Cut(start int, end int) *Buffer {
|
func (b *Buffer) Cut(start int, end int) *Buffer {
|
||||||
b.start += start
|
b.start += start
|
||||||
b.end = len(b.data) - end
|
b.end = len(b.data) - end
|
||||||
|
|
|
@ -38,3 +38,17 @@ func WriteTo(writer N.PacketWriter, buffer *buf.Buffer, addr net.Addr) (n int, e
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WriteVectorised(writer N.VectorisedWriter, data [][]byte) (n int, err error) {
|
||||||
|
var dataLen int
|
||||||
|
buffers := make([]*buf.Buffer, 0, len(data))
|
||||||
|
for _, p := range data {
|
||||||
|
dataLen += len(p)
|
||||||
|
buffers = append(buffers, buf.As(p))
|
||||||
|
}
|
||||||
|
err = writer.WriteVectorised(buffers)
|
||||||
|
if err == nil {
|
||||||
|
n = dataLen
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
109
common/bufio/vectorised.go
Normal file
109
common/bufio/vectorised.go
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
package bufio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateVectorisedWriter(writer any) (N.VectorisedWriter, bool) {
|
||||||
|
switch w := writer.(type) {
|
||||||
|
case N.VectorisedWriter:
|
||||||
|
return w, true
|
||||||
|
case *net.TCPConn:
|
||||||
|
return &NetVectorisedWriterWrapper{w}, true
|
||||||
|
case *net.UDPConn:
|
||||||
|
return &NetVectorisedWriterWrapper{w}, true
|
||||||
|
case *net.IPConn:
|
||||||
|
return &NetVectorisedWriterWrapper{w}, true
|
||||||
|
case *net.UnixConn:
|
||||||
|
return &NetVectorisedWriterWrapper{w}, true
|
||||||
|
case syscall.Conn:
|
||||||
|
rawConn, err := w.SyscallConn()
|
||||||
|
if err != nil {
|
||||||
|
return &SyscallVectorisedWriter{writer, rawConn}, true
|
||||||
|
}
|
||||||
|
case syscall.RawConn:
|
||||||
|
return &SyscallVectorisedWriter{writer, w}, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateVectorisedPacketWriter(writer any) (N.VectorisedPacketWriter, bool) {
|
||||||
|
switch w := writer.(type) {
|
||||||
|
case N.VectorisedPacketWriter:
|
||||||
|
return w, true
|
||||||
|
case syscall.Conn:
|
||||||
|
rawConn, err := w.SyscallConn()
|
||||||
|
if err != nil {
|
||||||
|
return &SyscallVectorisedPacketWriter{writer, rawConn}, true
|
||||||
|
}
|
||||||
|
case syscall.RawConn:
|
||||||
|
return &SyscallVectorisedPacketWriter{writer, w}, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ N.VectorisedWriter = (*NetVectorisedWriterWrapper)(nil)
|
||||||
|
|
||||||
|
type NetVectorisedWriterWrapper struct {
|
||||||
|
upstream io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *NetVectorisedWriterWrapper) WriteVectorised(buffers []*buf.Buffer) error {
|
||||||
|
defer buf.ReleaseMulti(buffers)
|
||||||
|
netBuffers := make(net.Buffers, 0, len(buffers))
|
||||||
|
for _, buffer := range buffers {
|
||||||
|
netBuffers = append(netBuffers, buffer.Bytes())
|
||||||
|
}
|
||||||
|
return common.Error(netBuffers.WriteTo(w.upstream))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *NetVectorisedWriterWrapper) Upstream() any {
|
||||||
|
return w.upstream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *NetVectorisedWriterWrapper) WriterReplaceable() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ N.VectorisedWriter = (*SyscallVectorisedWriter)(nil)
|
||||||
|
|
||||||
|
type SyscallVectorisedWriter struct {
|
||||||
|
upstream any
|
||||||
|
rawConn syscall.RawConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *SyscallVectorisedWriter) Upstream() any {
|
||||||
|
return w.upstream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *SyscallVectorisedWriter) WriterReplaceable() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ N.VectorisedPacketWriter = (*SyscallVectorisedPacketWriter)(nil)
|
||||||
|
|
||||||
|
type SyscallVectorisedPacketWriter struct {
|
||||||
|
upstream any
|
||||||
|
rawConn syscall.RawConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *SyscallVectorisedPacketWriter) Upstream() any {
|
||||||
|
return w.upstream
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ N.VectorisedPacketWriter = (*UnbindVectorisedPacketWriter)(nil)
|
||||||
|
|
||||||
|
type UnbindVectorisedPacketWriter struct {
|
||||||
|
N.VectorisedWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *UnbindVectorisedPacketWriter) WriteVectorisedPacket(buffers []*buf.Buffer, _ M.Socksaddr) error {
|
||||||
|
return w.WriteVectorised(buffers)
|
||||||
|
}
|
57
common/bufio/vectorised_unix.go
Normal file
57
common/bufio/vectorised_unix.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package bufio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (w *SyscallVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error {
|
||||||
|
defer buf.ReleaseMulti(buffers)
|
||||||
|
iovecList := make([]unix.Iovec, 0, len(buffers))
|
||||||
|
for _, buffer := range buffers {
|
||||||
|
var iovec unix.Iovec
|
||||||
|
iovec.Base = &buffer.Bytes()[0]
|
||||||
|
iovec.SetLen(buffer.Len())
|
||||||
|
iovecList = append(iovecList, iovec)
|
||||||
|
}
|
||||||
|
var innerErr unix.Errno
|
||||||
|
err := w.rawConn.Write(func(fd uintptr) (done bool) {
|
||||||
|
_, _, innerErr = unix.Syscall(unix.SYS_WRITEV, fd, uintptr(unsafe.Pointer(&iovecList[0])), uintptr(len(iovecList)))
|
||||||
|
return innerErr != unix.EAGAIN && innerErr != unix.EWOULDBLOCK
|
||||||
|
})
|
||||||
|
if innerErr != 0 {
|
||||||
|
err = innerErr
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *SyscallVectorisedPacketWriter) WriteVectorisedPacket(buffers []*buf.Buffer, destination M.Socksaddr) error {
|
||||||
|
iovecList := make([]unix.Iovec, 0, len(buffers))
|
||||||
|
for _, buffer := range buffers {
|
||||||
|
var iovec unix.Iovec
|
||||||
|
iovec.Base = &buffer.Bytes()[0]
|
||||||
|
iovec.SetLen(buffer.Len())
|
||||||
|
iovecList = append(iovecList, iovec)
|
||||||
|
}
|
||||||
|
name, nameLen := destination.Sockaddr()
|
||||||
|
var msgHdr unix.Msghdr
|
||||||
|
msgHdr.Name = (*byte)(name)
|
||||||
|
msgHdr.Namelen = nameLen
|
||||||
|
msgHdr.Iov = &iovecList[0]
|
||||||
|
msgHdr.SetIovlen(len(iovecList))
|
||||||
|
var innerErr unix.Errno
|
||||||
|
err := w.rawConn.Write(func(fd uintptr) (done bool) {
|
||||||
|
_, _, innerErr = unix.Syscall(unix.SYS_SENDMSG, fd, uintptr(unsafe.Pointer(&msgHdr)), 0)
|
||||||
|
return innerErr != unix.EAGAIN && innerErr != unix.EWOULDBLOCK
|
||||||
|
})
|
||||||
|
if innerErr != 0 {
|
||||||
|
err = innerErr
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
50
common/bufio/vectorised_windows.go
Normal file
50
common/bufio/vectorised_windows.go
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
package bufio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (w *SyscallVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error {
|
||||||
|
defer buf.ReleaseMulti(buffers)
|
||||||
|
iovecList := make([]*windows.WSABuf, len(buffers))
|
||||||
|
for i, buffer := range buffers {
|
||||||
|
iovecList[i] = &windows.WSABuf{
|
||||||
|
Len: uint32(buffer.Len()),
|
||||||
|
Buf: &buffer.Bytes()[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var n uint32
|
||||||
|
var innerErr error
|
||||||
|
err := w.rawConn.Write(func(fd uintptr) (done bool) {
|
||||||
|
innerErr = windows.WSASend(windows.Handle(fd), iovecList[0], uint32(len(iovecList)), &n, 0, nil, nil)
|
||||||
|
return innerErr != windows.WSAEWOULDBLOCK
|
||||||
|
})
|
||||||
|
if innerErr != nil {
|
||||||
|
err = innerErr
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *SyscallVectorisedPacketWriter) WriteVectorisedPacket(buffers []*buf.Buffer, destination M.Socksaddr) error {
|
||||||
|
defer buf.ReleaseMulti(buffers)
|
||||||
|
iovecList := make([]*windows.WSABuf, len(buffers))
|
||||||
|
for i, buffer := range buffers {
|
||||||
|
iovecList[i] = &windows.WSABuf{
|
||||||
|
Len: uint32(buffer.Len()),
|
||||||
|
Buf: &buffer.Bytes()[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var n uint32
|
||||||
|
var innerErr error
|
||||||
|
err := w.rawConn.Write(func(fd uintptr) (done bool) {
|
||||||
|
innerErr = windows.WSASendto(windows.Handle(fd), iovecList[0], uint32(len(iovecList)), &n, 0, destination.Sockaddr(), nil, nil)
|
||||||
|
return innerErr != windows.WSAEWOULDBLOCK
|
||||||
|
})
|
||||||
|
if innerErr != nil {
|
||||||
|
err = innerErr
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
31
common/metadata/addr_posix.go
Normal file
31
common/metadata/addr_posix.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ap Socksaddr) Sockaddr() (name unsafe.Pointer, nameLen uint32) {
|
||||||
|
if ap.IsFqdn() {
|
||||||
|
panic("bad sockaddr")
|
||||||
|
} else if ap.IsIPv4() {
|
||||||
|
rsa4 := syscall.RawSockaddrInet4{
|
||||||
|
Family: syscall.AF_INET,
|
||||||
|
Port: ap.Port,
|
||||||
|
Addr: ap.Addr.As4(),
|
||||||
|
}
|
||||||
|
name = unsafe.Pointer(&rsa4)
|
||||||
|
nameLen = syscall.SizeofSockaddrInet4
|
||||||
|
} else {
|
||||||
|
rsa6 := syscall.RawSockaddrInet6{
|
||||||
|
Family: syscall.AF_INET6,
|
||||||
|
Port: ap.Port,
|
||||||
|
Addr: ap.Addr.As16(),
|
||||||
|
}
|
||||||
|
name = unsafe.Pointer(&rsa6)
|
||||||
|
nameLen = syscall.SizeofSockaddrInet6
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
21
common/metadata/addr_windows.go
Normal file
21
common/metadata/addr_windows.go
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ap Socksaddr) Sockaddr() windows.Sockaddr {
|
||||||
|
if ap.IsFqdn() {
|
||||||
|
panic("bad sockaddr")
|
||||||
|
} else if ap.IsIPv4() {
|
||||||
|
return &windows.SockaddrInet4{
|
||||||
|
Port: int(ap.Port),
|
||||||
|
Addr: ap.Addr.As4(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return &windows.SockaddrInet6{
|
||||||
|
Port: int(ap.Port),
|
||||||
|
Addr: ap.Addr.As16(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
common/network/vectorised.go
Normal file
14
common/network/vectorised.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VectorisedWriter interface {
|
||||||
|
WriteVectorised(buffers []*buf.Buffer) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type VectorisedPacketWriter interface {
|
||||||
|
WriteVectorisedPacket(buffers []*buf.Buffer, destination M.Socksaddr) error
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: use vectorised writer
|
||||||
func WriteV(fd uintptr, data [][]byte) (int, error) {
|
func WriteV(fd uintptr, data [][]byte) (int, error) {
|
||||||
iovecs := make([]syscall.Iovec, len(data))
|
iovecs := make([]syscall.Iovec, len(data))
|
||||||
for i := range iovecs {
|
for i := range iovecs {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: use vectorised writer
|
||||||
func WriteV(fd uintptr, data [][]byte) (int, error) {
|
func WriteV(fd uintptr, data [][]byte) (int, error) {
|
||||||
var n uint32
|
var n uint32
|
||||||
buffers := make([]*syscall.WSABuf, len(data))
|
buffers := make([]*syscall.WSABuf, len(data))
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
// +----+------+------+----------+----------+----------+
|
// +----+------+------+----------+----------+----------+
|
||||||
|
|
||||||
type AssociatePacketConn struct {
|
type AssociatePacketConn struct {
|
||||||
N.PacketConn
|
N.NetPacketConn
|
||||||
addr net.Addr
|
addr net.Addr
|
||||||
remoteAddr M.Socksaddr
|
remoteAddr M.Socksaddr
|
||||||
underlying net.Conn
|
underlying net.Conn
|
||||||
|
@ -25,17 +25,17 @@ type AssociatePacketConn struct {
|
||||||
|
|
||||||
func NewAssociatePacketConn(conn net.PacketConn, remoteAddr M.Socksaddr, underlying net.Conn) *AssociatePacketConn {
|
func NewAssociatePacketConn(conn net.PacketConn, remoteAddr M.Socksaddr, underlying net.Conn) *AssociatePacketConn {
|
||||||
return &AssociatePacketConn{
|
return &AssociatePacketConn{
|
||||||
PacketConn: bufio.NewPacketConn(conn),
|
NetPacketConn: bufio.NewPacketConn(conn),
|
||||||
remoteAddr: remoteAddr,
|
remoteAddr: remoteAddr,
|
||||||
underlying: underlying,
|
underlying: underlying,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAssociateConn(conn net.Conn, remoteAddr M.Socksaddr, underlying net.Conn) *AssociatePacketConn {
|
func NewAssociateConn(conn net.Conn, remoteAddr M.Socksaddr, underlying net.Conn) *AssociatePacketConn {
|
||||||
return &AssociatePacketConn{
|
return &AssociatePacketConn{
|
||||||
PacketConn: bufio.NewUnbindPacketConn(conn),
|
NetPacketConn: bufio.NewUnbindPacketConn(conn),
|
||||||
remoteAddr: remoteAddr,
|
remoteAddr: remoteAddr,
|
||||||
underlying: underlying,
|
underlying: underlying,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ func (c *AssociatePacketConn) RemoteAddr() net.Addr {
|
||||||
//warn:unsafe
|
//warn:unsafe
|
||||||
func (c *AssociatePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *AssociatePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
buffer := buf.With(p)
|
buffer := buf.With(p)
|
||||||
n, _, err = bufio.ReadFrom(c.PacketConn, buffer)
|
n, _, err = bufio.ReadFrom(c.NetPacketConn, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func (c *AssociatePacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return bufio.WriteTo(c.PacketConn, buffer, c.addr)
|
return bufio.WriteTo(c.NetPacketConn, buffer, c.addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AssociatePacketConn) Read(b []byte) (n int, err error) {
|
func (c *AssociatePacketConn) Read(b []byte) (n int, err error) {
|
||||||
|
@ -89,7 +89,7 @@ func (c *AssociatePacketConn) Write(b []byte) (n int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AssociatePacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
func (c *AssociatePacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
||||||
_, addr, err := bufio.ReadFrom(c.PacketConn, buffer)
|
_, addr, err := bufio.ReadFrom(c.NetPacketConn, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return M.Socksaddr{}, err
|
return M.Socksaddr{}, err
|
||||||
}
|
}
|
||||||
|
@ -103,11 +103,11 @@ func (c *AssociatePacketConn) WritePacket(buffer *buf.Buffer, destination M.Sock
|
||||||
header := buf.With(buffer.ExtendHeader(3 + M.SocksaddrSerializer.AddrPortLen(destination)))
|
header := buf.With(buffer.ExtendHeader(3 + M.SocksaddrSerializer.AddrPortLen(destination)))
|
||||||
common.Must(header.WriteZeroN(3))
|
common.Must(header.WriteZeroN(3))
|
||||||
common.Must(M.SocksaddrSerializer.WriteAddrPort(header, destination))
|
common.Must(M.SocksaddrSerializer.WriteAddrPort(header, destination))
|
||||||
return common.Error(bufio.WriteTo(c.PacketConn, buffer, c.addr))
|
return common.Error(bufio.WriteTo(c.NetPacketConn, buffer, c.addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AssociatePacketConn) Upstream() any {
|
func (c *AssociatePacketConn) Upstream() any {
|
||||||
return c.PacketConn
|
return c.NetPacketConn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AssociatePacketConn) FrontHeadroom() int {
|
func (c *AssociatePacketConn) FrontHeadroom() int {
|
||||||
|
@ -116,7 +116,7 @@ func (c *AssociatePacketConn) FrontHeadroom() int {
|
||||||
|
|
||||||
func (c *AssociatePacketConn) Close() error {
|
func (c *AssociatePacketConn) Close() error {
|
||||||
return common.Close(
|
return common.Close(
|
||||||
c.PacketConn,
|
c.NetPacketConn,
|
||||||
c.underlying,
|
c.underlying,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
54
protocol/socks/packet_vectorised.go
Normal file
54
protocol/socks/packet_vectorised.go
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package socks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
"github.com/sagernet/sing/common/bufio"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ N.VectorisedPacketWriter = (*VectorisedAssociatePacketConn)(nil)
|
||||||
|
|
||||||
|
type VectorisedAssociatePacketConn struct {
|
||||||
|
AssociatePacketConn
|
||||||
|
N.VectorisedPacketWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVectorisedAssociatePacketConn(conn net.PacketConn, writer N.VectorisedPacketWriter, remoteAddr M.Socksaddr, underlying net.Conn) *VectorisedAssociatePacketConn {
|
||||||
|
return &VectorisedAssociatePacketConn{
|
||||||
|
AssociatePacketConn{
|
||||||
|
NetPacketConn: bufio.NewPacketConn(conn),
|
||||||
|
remoteAddr: remoteAddr,
|
||||||
|
underlying: underlying,
|
||||||
|
},
|
||||||
|
writer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVectorisedAssociateConn(conn net.Conn, writer N.VectorisedWriter, remoteAddr M.Socksaddr, underlying net.Conn) *VectorisedAssociatePacketConn {
|
||||||
|
return &VectorisedAssociatePacketConn{
|
||||||
|
AssociatePacketConn{
|
||||||
|
NetPacketConn: bufio.NewUnbindPacketConn(conn),
|
||||||
|
remoteAddr: remoteAddr,
|
||||||
|
underlying: underlying,
|
||||||
|
},
|
||||||
|
&bufio.UnbindVectorisedPacketWriter{VectorisedWriter: writer},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
defer header.Release()
|
||||||
|
common.Must(header.WriteZeroN(3))
|
||||||
|
common.Must(M.SocksaddrSerializer.WriteAddrPort(header, destination))
|
||||||
|
return v.VectorisedPacketWriter.WriteVectorisedPacket(append([]*buf.Buffer{header}, buffers...), destination)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *VectorisedAssociatePacketConn) FrontHeadroom() int {
|
||||||
|
return 0
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue