Improve multiplexer

This commit is contained in:
世界
2022-08-03 21:51:34 +08:00
parent 8e4de29409
commit 03890151d7
13 changed files with 247 additions and 56 deletions

View File

@@ -15,40 +15,44 @@ import (
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/x/list"
"github.com/hashicorp/yamux"
)
var _ N.Dialer = (*Client)(nil)
type Client struct {
access sync.Mutex
connections list.List[*yamux.Session]
connections list.List[abstractSession]
ctx context.Context
dialer N.Dialer
protocol Protocol
maxConnections int
minStreams int
maxStreams int
}
func NewClient(ctx context.Context, dialer N.Dialer, maxConnections int, minStreams int, maxStreams int) *Client {
func NewClient(ctx context.Context, dialer N.Dialer, protocol Protocol, maxConnections int, minStreams int, maxStreams int) *Client {
return &Client{
ctx: ctx,
dialer: dialer,
protocol: protocol,
maxConnections: maxConnections,
minStreams: minStreams,
maxStreams: maxStreams,
}
}
func NewClientWithOptions(ctx context.Context, dialer N.Dialer, options option.MultiplexOptions) N.Dialer {
func NewClientWithOptions(ctx context.Context, dialer N.Dialer, options option.MultiplexOptions) (N.Dialer, error) {
if !options.Enabled {
return dialer
return dialer, nil
}
if options.MaxConnections == 0 && options.MaxStreams == 0 {
options.MinStreams = 8
}
return NewClient(ctx, dialer, options.MaxConnections, options.MinStreams, options.MaxStreams)
protocol, err := ParseProtocol(options.Protocol)
if err != nil {
return nil, err
}
return NewClient(ctx, dialer, protocol, options.MaxConnections, options.MinStreams, options.MaxStreams), nil
}
func (c *Client) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
@@ -80,8 +84,8 @@ func (c *Client) ListenPacket(ctx context.Context, destination M.Socksaddr) (net
func (c *Client) openStream() (net.Conn, error) {
var (
session *yamux.Session
stream *yamux.Stream
session abstractSession
stream net.Conn
err error
)
for attempts := 0; attempts < 2; attempts++ {
@@ -89,7 +93,7 @@ func (c *Client) openStream() (net.Conn, error) {
if err != nil {
continue
}
stream, err = session.OpenStream()
stream, err = session.Open()
if err != nil {
continue
}
@@ -101,11 +105,11 @@ func (c *Client) openStream() (net.Conn, error) {
return &wrapStream{stream}, nil
}
func (c *Client) offer() (*yamux.Session, error) {
func (c *Client) offer() (abstractSession, error) {
c.access.Lock()
defer c.access.Unlock()
sessions := make([]*yamux.Session, 0, c.maxConnections)
sessions := make([]abstractSession, 0, c.maxConnections)
for element := c.connections.Front(); element != nil; {
if element.Value.IsClosed() {
nextElement := element.Next()
@@ -120,10 +124,7 @@ func (c *Client) offer() (*yamux.Session, error) {
if sLen == 0 {
return c.offerNew()
}
// session := common.MinBy(sessions, yamux.Session.NumStreams)
session := common.MinBy(sessions, func(it *yamux.Session) int {
return it.NumStreams()
})
session := common.MinBy(sessions, abstractSession.NumStreams)
numStreams := session.NumStreams()
if numStreams == 0 {
return session, nil
@@ -140,12 +141,12 @@ func (c *Client) offer() (*yamux.Session, error) {
return c.offerNew()
}
func (c *Client) offerNew() (*yamux.Session, error) {
func (c *Client) offerNew() (abstractSession, error) {
conn, err := c.dialer.DialContext(c.ctx, N.NetworkTCP, Destination)
if err != nil {
return nil, err
}
session, err := yamux.Client(conn, newMuxConfig())
session, err := c.protocol.newClient(&protocolConn{Conn: conn, protocol: c.protocol})
if err != nil {
return nil, err
}
@@ -170,7 +171,7 @@ type ClientConn struct {
}
func (c *ClientConn) readResponse() error {
response, err := ReadResponse(c.Conn)
response, err := ReadStreamResponse(c.Conn)
if err != nil {
return err
}
@@ -195,7 +196,7 @@ func (c *ClientConn) Write(b []byte) (n int, err error) {
if c.requestWrite {
return c.Conn.Write(b)
}
request := Request{
request := StreamRequest{
Network: N.NetworkTCP,
Destination: c.destination,
}
@@ -203,7 +204,7 @@ func (c *ClientConn) Write(b []byte) (n int, err error) {
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
EncodeRequest(request, buffer)
EncodeStreamRequest(request, buffer)
buffer.Write(b)
_, err = c.Conn.Write(buffer.Bytes())
if err != nil {
@@ -255,7 +256,7 @@ type ClientPacketConn struct {
}
func (c *ClientPacketConn) readResponse() error {
response, err := ReadResponse(c.ExtendedConn)
response, err := ReadStreamResponse(c.ExtendedConn)
if err != nil {
return err
}
@@ -285,7 +286,7 @@ func (c *ClientPacketConn) Read(b []byte) (n int, err error) {
}
func (c *ClientPacketConn) writeRequest(payload []byte) (n int, err error) {
request := Request{
request := StreamRequest{
Network: N.NetworkUDP,
Destination: c.destination,
}
@@ -297,7 +298,7 @@ func (c *ClientPacketConn) writeRequest(payload []byte) (n int, err error) {
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
EncodeRequest(request, buffer)
EncodeStreamRequest(request, buffer)
if len(payload) > 0 {
common.Must(
binary.Write(buffer, binary.BigEndian, uint16(len(payload))),
@@ -363,7 +364,7 @@ type ClientPacketAddrConn struct {
}
func (c *ClientPacketAddrConn) readResponse() error {
response, err := ReadResponse(c.ExtendedConn)
response, err := ReadStreamResponse(c.ExtendedConn)
if err != nil {
return err
}
@@ -399,7 +400,7 @@ func (c *ClientPacketAddrConn) ReadFrom(p []byte) (n int, addr net.Addr, err err
}
func (c *ClientPacketAddrConn) writeRequest(payload []byte, destination M.Socksaddr) (n int, err error) {
request := Request{
request := StreamRequest{
Network: N.NetworkUDP,
Destination: c.destination,
PacketAddr: true,
@@ -412,7 +413,7 @@ func (c *ClientPacketAddrConn) writeRequest(payload []byte, destination M.Socksa
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
EncodeRequest(request, buffer)
EncodeStreamRequest(request, buffer)
if len(payload) > 0 {
common.Must(
M.SocksaddrSerializer.WriteAddrPort(buffer, destination),