mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
Improve multiplex
This commit is contained in:
parent
d8810b6e8f
commit
8545e41b2f
@ -28,9 +28,10 @@ type Client struct {
|
|||||||
maxConnections int
|
maxConnections int
|
||||||
minStreams int
|
minStreams int
|
||||||
maxStreams int
|
maxStreams int
|
||||||
|
paddingEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(ctx context.Context, dialer N.Dialer, protocol Protocol, maxConnections int, minStreams int, maxStreams int) *Client {
|
func NewClient(ctx context.Context, dialer N.Dialer, protocol Protocol, maxConnections int, minStreams int, maxStreams int, paddingEnabled bool) (*Client, error) {
|
||||||
return &Client{
|
return &Client{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
@ -38,7 +39,8 @@ func NewClient(ctx context.Context, dialer N.Dialer, protocol Protocol, maxConne
|
|||||||
maxConnections: maxConnections,
|
maxConnections: maxConnections,
|
||||||
minStreams: minStreams,
|
minStreams: minStreams,
|
||||||
maxStreams: maxStreams,
|
maxStreams: maxStreams,
|
||||||
}
|
paddingEnabled: paddingEnabled,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientWithOptions(ctx context.Context, dialer N.Dialer, options option.MultiplexOptions) (*Client, error) {
|
func NewClientWithOptions(ctx context.Context, dialer N.Dialer, options option.MultiplexOptions) (*Client, error) {
|
||||||
@ -52,7 +54,7 @@ func NewClientWithOptions(ctx context.Context, dialer N.Dialer, options option.M
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return NewClient(ctx, dialer, protocol, options.MaxConnections, options.MinStreams, options.MaxStreams), nil
|
return NewClient(ctx, dialer, protocol, options.MaxConnections, options.MinStreams, options.MaxStreams, options.Padding)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (c *Client) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
@ -145,10 +147,19 @@ func (c *Client) offerNew() (abstractSession, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if vectorisedWriter, isVectorised := bufio.CreateVectorisedWriter(conn); isVectorised {
|
var version byte
|
||||||
conn = &vectorisedProtocolConn{protocolConn{Conn: conn, protocol: c.protocol}, vectorisedWriter}
|
if c.paddingEnabled {
|
||||||
|
version = Version1
|
||||||
} else {
|
} else {
|
||||||
conn = &protocolConn{Conn: conn, protocol: c.protocol}
|
version = Version0
|
||||||
|
}
|
||||||
|
conn = newProtocolConn(conn, Request{
|
||||||
|
Version: version,
|
||||||
|
Protocol: c.protocol,
|
||||||
|
PaddingEnabled: c.paddingEnabled,
|
||||||
|
})
|
||||||
|
if c.paddingEnabled {
|
||||||
|
conn = newPaddingConn(conn)
|
||||||
}
|
}
|
||||||
session, err := c.protocol.newClient(conn)
|
session, err := c.protocol.newClient(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -213,7 +224,7 @@ func (c *ClientConn) Write(b []byte) (n int, err error) {
|
|||||||
Network: N.NetworkTCP,
|
Network: N.NetworkTCP,
|
||||||
Destination: c.destination,
|
Destination: c.destination,
|
||||||
}
|
}
|
||||||
_buffer := buf.StackNewSize(requestLen(request) + len(b))
|
_buffer := buf.StackNewSize(streamRequestLen(request) + len(b))
|
||||||
defer common.KeepAlive(_buffer)
|
defer common.KeepAlive(_buffer)
|
||||||
buffer := common.Dup(_buffer)
|
buffer := common.Dup(_buffer)
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
@ -307,7 +318,7 @@ func (c *ClientPacketConn) writeRequest(payload []byte) (n int, err error) {
|
|||||||
Network: N.NetworkUDP,
|
Network: N.NetworkUDP,
|
||||||
Destination: c.destination,
|
Destination: c.destination,
|
||||||
}
|
}
|
||||||
rLen := requestLen(request)
|
rLen := streamRequestLen(request)
|
||||||
if len(payload) > 0 {
|
if len(payload) > 0 {
|
||||||
rLen += 2 + len(payload)
|
rLen += 2 + len(payload)
|
||||||
}
|
}
|
||||||
@ -452,7 +463,7 @@ func (c *ClientPacketAddrConn) writeRequest(payload []byte, destination M.Socksa
|
|||||||
Destination: c.destination,
|
Destination: c.destination,
|
||||||
PacketAddr: true,
|
PacketAddr: true,
|
||||||
}
|
}
|
||||||
rLen := requestLen(request)
|
rLen := streamRequestLen(request)
|
||||||
if len(payload) > 0 {
|
if len(payload) > 0 {
|
||||||
rLen += M.SocksaddrSerializer.AddrPortLen(destination) + 2 + len(payload)
|
rLen += M.SocksaddrSerializer.AddrPortLen(destination) + 2 + len(payload)
|
||||||
}
|
}
|
||||||
|
240
common/mux/padding.go
Normal file
240
common/mux/padding.go
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
package mux
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
"github.com/sagernet/sing/common/bufio"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/common/rw"
|
||||||
|
)
|
||||||
|
|
||||||
|
const kFirstPaddings = 16
|
||||||
|
|
||||||
|
type paddingConn struct {
|
||||||
|
N.ExtendedConn
|
||||||
|
writer N.VectorisedWriter
|
||||||
|
readPadding int
|
||||||
|
writePadding int
|
||||||
|
readRemaining int
|
||||||
|
paddingRemaining int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPaddingConn(conn net.Conn) net.Conn {
|
||||||
|
writer, isVectorised := bufio.CreateVectorisedWriter(conn)
|
||||||
|
if isVectorised {
|
||||||
|
return &vectorisedPaddingConn{
|
||||||
|
paddingConn{
|
||||||
|
ExtendedConn: bufio.NewExtendedConn(conn),
|
||||||
|
writer: bufio.NewVectorisedWriter(conn),
|
||||||
|
},
|
||||||
|
writer,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return &paddingConn{
|
||||||
|
ExtendedConn: bufio.NewExtendedConn(conn),
|
||||||
|
writer: bufio.NewVectorisedWriter(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *paddingConn) Read(p []byte) (n int, err error) {
|
||||||
|
if c.readRemaining > 0 {
|
||||||
|
if len(p) > c.readRemaining {
|
||||||
|
p = p[:c.readRemaining]
|
||||||
|
}
|
||||||
|
n, err = c.ExtendedConn.Read(p)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.readRemaining -= n
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.paddingRemaining > 0 {
|
||||||
|
err = rw.SkipN(c.ExtendedConn, c.paddingRemaining)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.paddingRemaining = 0
|
||||||
|
}
|
||||||
|
if c.readPadding < kFirstPaddings {
|
||||||
|
var paddingHdr []byte
|
||||||
|
if len(p) >= 4 {
|
||||||
|
paddingHdr = p[:4]
|
||||||
|
} else {
|
||||||
|
_paddingHdr := make([]byte, 4)
|
||||||
|
defer common.KeepAlive(_paddingHdr)
|
||||||
|
paddingHdr = common.Dup(_paddingHdr)
|
||||||
|
}
|
||||||
|
_, err = io.ReadFull(c.ExtendedConn, paddingHdr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
originalDataSize := int(binary.BigEndian.Uint16(paddingHdr[:2]))
|
||||||
|
paddingLen := int(binary.BigEndian.Uint16(paddingHdr[2:]))
|
||||||
|
if len(p) > originalDataSize {
|
||||||
|
p = p[:originalDataSize]
|
||||||
|
}
|
||||||
|
n, err = c.ExtendedConn.Read(p)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.readPadding++
|
||||||
|
c.readRemaining = originalDataSize - n
|
||||||
|
c.paddingRemaining = paddingLen
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return c.ExtendedConn.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *paddingConn) Write(p []byte) (n int, err error) {
|
||||||
|
for pLen := len(p); pLen > 0; {
|
||||||
|
var data []byte
|
||||||
|
if pLen > 65535 {
|
||||||
|
data = p[:65535]
|
||||||
|
p = p[65535:]
|
||||||
|
pLen -= 65535
|
||||||
|
} else {
|
||||||
|
data = p
|
||||||
|
pLen = 0
|
||||||
|
}
|
||||||
|
var writeN int
|
||||||
|
writeN, err = c.write(data)
|
||||||
|
n += writeN
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *paddingConn) write(p []byte) (n int, err error) {
|
||||||
|
if c.writePadding < kFirstPaddings {
|
||||||
|
paddingLen := 256 + rand.Intn(512)
|
||||||
|
_buffer := buf.StackNewSize(4 + len(p) + paddingLen)
|
||||||
|
defer common.KeepAlive(_buffer)
|
||||||
|
buffer := common.Dup(_buffer)
|
||||||
|
defer buffer.Release()
|
||||||
|
header := buffer.Extend(4)
|
||||||
|
binary.BigEndian.PutUint16(header[:2], uint16(len(p)))
|
||||||
|
binary.BigEndian.PutUint16(header[2:], uint16(paddingLen))
|
||||||
|
common.Must1(buffer.Write(p))
|
||||||
|
buffer.Extend(paddingLen)
|
||||||
|
_, err = c.ExtendedConn.Write(buffer.Bytes())
|
||||||
|
if err == nil {
|
||||||
|
n = len(p)
|
||||||
|
}
|
||||||
|
c.writePadding++
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return c.ExtendedConn.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *paddingConn) ReadBuffer(buffer *buf.Buffer) error {
|
||||||
|
p := buffer.FreeBytes()
|
||||||
|
if c.readRemaining > 0 {
|
||||||
|
if len(p) > c.readRemaining {
|
||||||
|
p = p[:c.readRemaining]
|
||||||
|
}
|
||||||
|
n, err := c.ExtendedConn.Read(p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.readRemaining -= n
|
||||||
|
buffer.Truncate(n)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if c.paddingRemaining > 0 {
|
||||||
|
err := rw.SkipN(c.ExtendedConn, c.paddingRemaining)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.paddingRemaining = 0
|
||||||
|
}
|
||||||
|
if c.readPadding < kFirstPaddings {
|
||||||
|
var paddingHdr []byte
|
||||||
|
if len(p) >= 4 {
|
||||||
|
paddingHdr = p[:4]
|
||||||
|
} else {
|
||||||
|
_paddingHdr := make([]byte, 4)
|
||||||
|
defer common.KeepAlive(_paddingHdr)
|
||||||
|
paddingHdr = common.Dup(_paddingHdr)
|
||||||
|
}
|
||||||
|
_, err := io.ReadFull(c.ExtendedConn, paddingHdr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
originalDataSize := int(binary.BigEndian.Uint16(paddingHdr[:2]))
|
||||||
|
paddingLen := int(binary.BigEndian.Uint16(paddingHdr[2:]))
|
||||||
|
|
||||||
|
if len(p) > originalDataSize {
|
||||||
|
p = p[:originalDataSize]
|
||||||
|
}
|
||||||
|
n, err := c.ExtendedConn.Read(p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.readPadding++
|
||||||
|
c.readRemaining = originalDataSize - n
|
||||||
|
c.paddingRemaining = paddingLen
|
||||||
|
buffer.Truncate(n)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.ExtendedConn.ReadBuffer(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *paddingConn) WriteBuffer(buffer *buf.Buffer) error {
|
||||||
|
if c.writePadding < kFirstPaddings {
|
||||||
|
bufferLen := buffer.Len()
|
||||||
|
if bufferLen > 65535 {
|
||||||
|
return common.Error(c.Write(buffer.Bytes()))
|
||||||
|
}
|
||||||
|
paddingLen := 256 + rand.Intn(512)
|
||||||
|
header := buffer.ExtendHeader(4)
|
||||||
|
binary.BigEndian.PutUint16(header[:2], uint16(bufferLen))
|
||||||
|
binary.BigEndian.PutUint16(header[2:], uint16(paddingLen))
|
||||||
|
buffer.Extend(paddingLen)
|
||||||
|
c.writePadding++
|
||||||
|
}
|
||||||
|
return c.ExtendedConn.WriteBuffer(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *paddingConn) FrontHeadroom() int {
|
||||||
|
return 4 + 256 + 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
type vectorisedPaddingConn struct {
|
||||||
|
paddingConn
|
||||||
|
writer N.VectorisedWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *vectorisedPaddingConn) WriteVectorised(buffers []*buf.Buffer) error {
|
||||||
|
if c.writePadding < kFirstPaddings {
|
||||||
|
bufferLen := buf.LenMulti(buffers)
|
||||||
|
if bufferLen > 65535 {
|
||||||
|
defer buf.ReleaseMulti(buffers)
|
||||||
|
for _, buffer := range buffers {
|
||||||
|
_, err := c.Write(buffer.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
paddingLen := 256 + rand.Intn(512)
|
||||||
|
header := buf.NewSize(4)
|
||||||
|
common.Must(
|
||||||
|
binary.Write(header, binary.BigEndian, uint16(bufferLen)),
|
||||||
|
binary.Write(header, binary.BigEndian, uint16(paddingLen)),
|
||||||
|
)
|
||||||
|
c.writePadding++
|
||||||
|
padding := buf.NewSize(paddingLen)
|
||||||
|
padding.Extend(paddingLen)
|
||||||
|
buffers = append(append([]*buf.Buffer{header}, buffers...), padding)
|
||||||
|
}
|
||||||
|
return c.writer.WriteVectorised(buffers)
|
||||||
|
}
|
@ -3,6 +3,7 @@ package mux
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
@ -113,11 +114,14 @@ func (p Protocol) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version0 = 0
|
Version0 = iota
|
||||||
|
Version1
|
||||||
)
|
)
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Protocol Protocol
|
Version byte
|
||||||
|
Protocol Protocol
|
||||||
|
PaddingEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadRequest(reader io.Reader) (*Request, error) {
|
func ReadRequest(reader io.Reader) (*Request, error) {
|
||||||
@ -125,19 +129,60 @@ func ReadRequest(reader io.Reader) (*Request, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if version != version0 {
|
if version < Version0 || version > Version1 {
|
||||||
return nil, E.New("unsupported version: ", version)
|
return nil, E.New("unsupported version: ", version)
|
||||||
}
|
}
|
||||||
protocol, err := rw.ReadByte(reader)
|
protocol, err := rw.ReadByte(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Request{Protocol: Protocol(protocol)}, nil
|
var paddingEnabled bool
|
||||||
|
if version == Version1 {
|
||||||
|
err = binary.Read(reader, binary.BigEndian, &paddingEnabled)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if paddingEnabled {
|
||||||
|
var paddingLen uint16
|
||||||
|
err = binary.Read(reader, binary.BigEndian, &paddingLen)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = rw.SkipN(reader, int(paddingLen))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &Request{Version: version, Protocol: Protocol(protocol), PaddingEnabled: paddingEnabled}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func EncodeRequest(buffer *buf.Buffer, request Request) {
|
func EncodeRequest(request Request, payload []byte) *buf.Buffer {
|
||||||
buffer.WriteByte(version0)
|
var requestLen int
|
||||||
buffer.WriteByte(byte(request.Protocol))
|
requestLen += 2
|
||||||
|
var paddingLen uint16
|
||||||
|
if request.Version == Version1 {
|
||||||
|
requestLen += 1
|
||||||
|
if request.PaddingEnabled {
|
||||||
|
requestLen += 2
|
||||||
|
paddingLen = uint16(256 + rand.Intn(512))
|
||||||
|
requestLen += int(paddingLen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer := buf.NewSize(requestLen + len(payload))
|
||||||
|
common.Must(
|
||||||
|
buffer.WriteByte(request.Version),
|
||||||
|
buffer.WriteByte(byte(request.Protocol)),
|
||||||
|
)
|
||||||
|
if request.Version == Version1 {
|
||||||
|
common.Must(binary.Write(buffer, binary.BigEndian, request.PaddingEnabled))
|
||||||
|
if request.PaddingEnabled {
|
||||||
|
common.Must(binary.Write(buffer, binary.BigEndian, paddingLen))
|
||||||
|
buffer.Extend(int(paddingLen))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
common.Must1(buffer.Write(payload))
|
||||||
|
return buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -174,7 +219,7 @@ func ReadStreamRequest(reader io.Reader) (*StreamRequest, error) {
|
|||||||
return &StreamRequest{network, destination, udpAddr}, nil
|
return &StreamRequest{network, destination, udpAddr}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestLen(request StreamRequest) int {
|
func streamRequestLen(request StreamRequest) int {
|
||||||
var rLen int
|
var rLen int
|
||||||
rLen += 1 // version
|
rLen += 1 // version
|
||||||
rLen += 2 // flags
|
rLen += 2 // flags
|
||||||
|
@ -22,6 +22,9 @@ func NewConnection(ctx context.Context, router adapter.Router, errorHandler E.Ha
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if request.PaddingEnabled {
|
||||||
|
conn = newPaddingConn(conn)
|
||||||
|
}
|
||||||
session, err := request.Protocol.newServer(conn)
|
session, err := request.Protocol.newServer(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
@ -50,23 +49,35 @@ func (y *yamuxSession) CanTakeNewRequest() bool {
|
|||||||
|
|
||||||
type protocolConn struct {
|
type protocolConn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
protocol Protocol
|
request Request
|
||||||
protocolWritten bool
|
protocolWritten bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newProtocolConn(conn net.Conn, request Request) net.Conn {
|
||||||
|
writer, isVectorised := bufio.CreateVectorisedWriter(conn)
|
||||||
|
if isVectorised {
|
||||||
|
return &vectorisedProtocolConn{
|
||||||
|
protocolConn{
|
||||||
|
Conn: conn,
|
||||||
|
request: request,
|
||||||
|
},
|
||||||
|
writer,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return &protocolConn{
|
||||||
|
Conn: conn,
|
||||||
|
request: request,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *protocolConn) Write(p []byte) (n int, err error) {
|
func (c *protocolConn) Write(p []byte) (n int, err error) {
|
||||||
if c.protocolWritten {
|
if c.protocolWritten {
|
||||||
return c.Conn.Write(p)
|
return c.Conn.Write(p)
|
||||||
}
|
}
|
||||||
_buffer := buf.StackNewSize(2 + len(p))
|
buffer := EncodeRequest(c.request, p)
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
|
||||||
EncodeRequest(buffer, Request{
|
|
||||||
Protocol: c.protocol,
|
|
||||||
})
|
|
||||||
common.Must(common.Error(buffer.Write(p)))
|
|
||||||
n, err = c.Conn.Write(buffer.Bytes())
|
n, err = c.Conn.Write(buffer.Bytes())
|
||||||
|
buffer.Release()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
@ -87,20 +98,14 @@ func (c *protocolConn) Upstream() any {
|
|||||||
|
|
||||||
type vectorisedProtocolConn struct {
|
type vectorisedProtocolConn struct {
|
||||||
protocolConn
|
protocolConn
|
||||||
N.VectorisedWriter
|
writer N.VectorisedWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *vectorisedProtocolConn) WriteVectorised(buffers []*buf.Buffer) error {
|
func (c *vectorisedProtocolConn) WriteVectorised(buffers []*buf.Buffer) error {
|
||||||
if c.protocolWritten {
|
if c.protocolWritten {
|
||||||
return c.VectorisedWriter.WriteVectorised(buffers)
|
return c.writer.WriteVectorised(buffers)
|
||||||
}
|
}
|
||||||
c.protocolWritten = true
|
c.protocolWritten = true
|
||||||
_buffer := buf.StackNewSize(2)
|
buffer := EncodeRequest(c.request, nil)
|
||||||
defer common.KeepAlive(_buffer)
|
return c.writer.WriteVectorised(append([]*buf.Buffer{buffer}, buffers...))
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
|
||||||
EncodeRequest(buffer, Request{
|
|
||||||
Protocol: c.protocol,
|
|
||||||
})
|
|
||||||
return c.VectorisedWriter.WriteVectorised(append([]*buf.Buffer{buffer}, buffers...))
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
"protocol": "smux",
|
"protocol": "smux",
|
||||||
"max_connections": 4,
|
"max_connections": 4,
|
||||||
"min_streams": 4,
|
"min_streams": 4,
|
||||||
"max_streams": 0
|
"max_streams": 0,
|
||||||
|
"padding": false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -49,3 +50,12 @@ Conflict with `max_streams`.
|
|||||||
Maximum multiplexed streams in a connection before opening a new connection.
|
Maximum multiplexed streams in a connection before opening a new connection.
|
||||||
|
|
||||||
Conflict with `max_connections` and `min_streams`.
|
Conflict with `max_connections` and `min_streams`.
|
||||||
|
|
||||||
|
#### padding
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
Requires sing-box server version 1.3-beta9 or later.
|
||||||
|
|
||||||
|
Enable padding.
|
||||||
|
|
||||||
|
@ -48,4 +48,13 @@
|
|||||||
|
|
||||||
在打开新连接之前,连接中的最大多路复用流数量。
|
在打开新连接之前,连接中的最大多路复用流数量。
|
||||||
|
|
||||||
与 `max_connections` 和 `min_streams` 冲突。
|
与 `max_connections` 和 `min_streams` 冲突。
|
||||||
|
|
||||||
|
#### padding
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
需要 sing-box 服务器版本 1.3-beta9 或更高。
|
||||||
|
|
||||||
|
启用填充。
|
||||||
|
|
||||||
|
@ -150,4 +150,5 @@ type MultiplexOptions struct {
|
|||||||
MaxConnections int `json:"max_connections,omitempty"`
|
MaxConnections int `json:"max_connections,omitempty"`
|
||||||
MinStreams int `json:"min_streams,omitempty"`
|
MinStreams int `json:"min_streams,omitempty"`
|
||||||
MaxStreams int `json:"max_streams,omitempty"`
|
MaxStreams int `json:"max_streams,omitempty"`
|
||||||
|
Padding bool `json:"padding,omitempty"`
|
||||||
}
|
}
|
||||||
|
13
test/go.mod
13
test/go.mod
@ -10,7 +10,7 @@ require (
|
|||||||
github.com/docker/docker v20.10.18+incompatible
|
github.com/docker/docker v20.10.18+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/gofrs/uuid/v5 v5.0.0
|
github.com/gofrs/uuid/v5 v5.0.0
|
||||||
github.com/sagernet/sing v0.2.4-0.20230419153323-5fae6fa434c1
|
github.com/sagernet/sing v0.2.4
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507
|
||||||
github.com/spyzhov/ajson v0.7.1
|
github.com/spyzhov/ajson v0.7.1
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
@ -21,7 +21,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
berty.tech/go-libtor v1.0.385 // indirect
|
berty.tech/go-libtor v1.0.385 // indirect
|
||||||
github.com/Dreamacro/clash v1.15.0 // indirect
|
github.com/Dreamacro/clash v1.15.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.5.1 // indirect
|
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
github.com/caddyserver/certmagic v0.17.2 // indirect
|
github.com/caddyserver/certmagic v0.17.2 // indirect
|
||||||
@ -72,13 +72,13 @@ require (
|
|||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc // indirect
|
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc // indirect
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b // indirect
|
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b // indirect
|
||||||
github.com/sagernet/sing-tun v0.1.4-0.20230420014302-db67add64fae // indirect
|
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b // indirect
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 // indirect
|
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 // indirect
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 // indirect
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 // indirect
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c // indirect
|
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
@ -92,13 +92,12 @@ require (
|
|||||||
golang.org/x/mod v0.8.0 // indirect
|
golang.org/x/mod v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.7.0 // indirect
|
golang.org/x/sys v0.7.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||||
golang.org/x/tools v0.6.0 // indirect
|
golang.org/x/tools v0.6.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||||
google.golang.org/grpc v1.54.0 // indirect
|
google.golang.org/grpc v1.54.0 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gotest.tools/v3 v3.4.0 // indirect
|
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 // indirect
|
||||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c // indirect
|
|
||||||
lukechampine.com/blake3 v1.1.7 // indirect
|
lukechampine.com/blake3 v1.1.7 // indirect
|
||||||
)
|
)
|
||||||
|
31
test/go.sum
31
test/go.sum
@ -3,8 +3,8 @@ berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+f
|
|||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||||
github.com/Dreamacro/clash v1.15.0 h1:mlpD950VEggXZBNahV66hyKDRxcczkj3vymoAt78KyE=
|
github.com/Dreamacro/clash v1.15.0 h1:mlpD950VEggXZBNahV66hyKDRxcczkj3vymoAt78KyE=
|
||||||
github.com/Dreamacro/clash v1.15.0/go.mod h1:WNH69bN11LiAdgdSr4hpkEuXVMfBbWyhEKMCTx9BtNE=
|
github.com/Dreamacro/clash v1.15.0/go.mod h1:WNH69bN11LiAdgdSr4hpkEuXVMfBbWyhEKMCTx9BtNE=
|
||||||
github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
|
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||||
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
@ -126,16 +126,16 @@ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byL
|
|||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing v0.2.4-0.20230419153323-5fae6fa434c1 h1:CdzNL25lzfVo0NMeghPqsupNsWvkzrbrUt5t8DoDPcQ=
|
github.com/sagernet/sing v0.2.4 h1:gC8BR5sglbJZX23RtMyFa8EETP9YEUADhfbEzU1yVbo=
|
||||||
github.com/sagernet/sing v0.2.4-0.20230419153323-5fae6fa434c1/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
github.com/sagernet/sing v0.2.4/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc h1:hmbuqKv48SAjiKPoqtJGvS5pEHVPZjTHq9CPwQY2cZ4=
|
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc h1:hmbuqKv48SAjiKPoqtJGvS5pEHVPZjTHq9CPwQY2cZ4=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
|
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507 h1:bAHZCdWqJkb8LEW98+YsMVDXGRMUVjka8IC+St6ot88=
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507 h1:bAHZCdWqJkb8LEW98+YsMVDXGRMUVjka8IC+St6ot88=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507/go.mod h1:UJjvQGw0lyYaDGIDvUraL16fwaAEH1WFw1Y6sUcMPog=
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507/go.mod h1:UJjvQGw0lyYaDGIDvUraL16fwaAEH1WFw1Y6sUcMPog=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4=
|
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI=
|
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI=
|
||||||
github.com/sagernet/sing-tun v0.1.4-0.20230420014302-db67add64fae h1:yNKqOPKX9GnnEMvnm9ZVsIyMuMsU0x6uCJQMwAhGafA=
|
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b h1:9NsciSJGwzdkXwVvT2c2g+RvkTVkANeBLr2l+soJ7LM=
|
||||||
github.com/sagernet/sing-tun v0.1.4-0.20230420014302-db67add64fae/go.mod h1:F7hYqaFR7RRs0aLj3gHDt+v18mpD5apJwPUfTd4e5HQ=
|
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b/go.mod h1:DD7Ce2Gt0GFc6I/1+Uw4D/aUlBsGqrQsC52CMK/V818=
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U=
|
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U=
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3/go.mod h1:yKrAr+dqZd64DxBXCHWrYicp+n4qbqO73mtwv3dck8U=
|
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3/go.mod h1:yKrAr+dqZd64DxBXCHWrYicp+n4qbqO73mtwv3dck8U=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
||||||
@ -146,9 +146,8 @@ github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfI
|
|||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM=
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM=
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2dKX7EQP++1JLNtw4C2TNxd4/ov8YUpOPOSo=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
|
||||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/spyzhov/ajson v0.7.1 h1:1MDIlPc6x0zjNtpa7tDzRAyFAvRX+X8ZsvtYz5lZg6A=
|
github.com/spyzhov/ajson v0.7.1 h1:1MDIlPc6x0zjNtpa7tDzRAyFAvRX+X8ZsvtYz5lZg6A=
|
||||||
@ -156,7 +155,6 @@ github.com/spyzhov/ajson v0.7.1/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzy
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
@ -216,13 +214,10 @@ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
|||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -241,13 +236,12 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
@ -270,8 +264,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||||
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 h1:zUQYeyyPLnSR6yMvLSOmLH37xDWCZ7BqlpE69fE5K3Q=
|
||||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4=
|
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q=
|
||||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
|
|
||||||
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
||||||
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||||
|
@ -18,22 +18,40 @@ var muxProtocols = []mux.Protocol{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestVMessSMux(t *testing.T) {
|
func TestVMessSMux(t *testing.T) {
|
||||||
testVMessMux(t, mux.ProtocolSMux.String())
|
testVMessMux(t, option.MultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: mux.ProtocolSMux.String(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShadowsocksMux(t *testing.T) {
|
func TestShadowsocksMux(t *testing.T) {
|
||||||
for _, protocol := range muxProtocols {
|
for _, protocol := range muxProtocols {
|
||||||
t.Run(protocol.String(), func(t *testing.T) {
|
t.Run(protocol.String(), func(t *testing.T) {
|
||||||
testShadowsocksMux(t, protocol.String())
|
testShadowsocksMux(t, option.MultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: protocol.String(),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShadowsockH2Mux(t *testing.T) {
|
func TestShadowsockH2Mux(t *testing.T) {
|
||||||
testShadowsocksMux(t, mux.ProtocolH2Mux.String())
|
testShadowsocksMux(t, option.MultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: mux.ProtocolH2Mux.String(),
|
||||||
|
Padding: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testShadowsocksMux(t *testing.T, protocol string) {
|
func TestShadowsockSMuxPadding(t *testing.T) {
|
||||||
|
testShadowsocksMux(t, option.MultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: mux.ProtocolSMux.String(),
|
||||||
|
Padding: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testShadowsocksMux(t *testing.T, options option.MultiplexOptions) {
|
||||||
method := shadowaead_2022.List[0]
|
method := shadowaead_2022.List[0]
|
||||||
password := mkBase64(t, 16)
|
password := mkBase64(t, 16)
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
@ -72,12 +90,9 @@ func testShadowsocksMux(t *testing.T, protocol string) {
|
|||||||
Server: "127.0.0.1",
|
Server: "127.0.0.1",
|
||||||
ServerPort: serverPort,
|
ServerPort: serverPort,
|
||||||
},
|
},
|
||||||
Method: method,
|
Method: method,
|
||||||
Password: password,
|
Password: password,
|
||||||
MultiplexOptions: &option.MultiplexOptions{
|
MultiplexOptions: &options,
|
||||||
Enabled: true,
|
|
||||||
Protocol: protocol,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -95,7 +110,7 @@ func testShadowsocksMux(t *testing.T, protocol string) {
|
|||||||
testSuit(t, clientPort, testPort)
|
testSuit(t, clientPort, testPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testVMessMux(t *testing.T, protocol string) {
|
func testVMessMux(t *testing.T, options option.MultiplexOptions) {
|
||||||
user, _ := uuid.NewV4()
|
user, _ := uuid.NewV4()
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
Inbounds: []option.Inbound{
|
Inbounds: []option.Inbound{
|
||||||
@ -136,12 +151,9 @@ func testVMessMux(t *testing.T, protocol string) {
|
|||||||
Server: "127.0.0.1",
|
Server: "127.0.0.1",
|
||||||
ServerPort: serverPort,
|
ServerPort: serverPort,
|
||||||
},
|
},
|
||||||
Security: "auto",
|
Security: "auto",
|
||||||
UUID: user.String(),
|
UUID: user.String(),
|
||||||
Multiplex: &option.MultiplexOptions{
|
Multiplex: &options,
|
||||||
Enabled: true,
|
|
||||||
Protocol: protocol,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user