chore: allow to set max-open-streams for tuic

This commit is contained in:
wwqgtxx 2022-11-27 09:38:20 +08:00
parent 896d30b151
commit 423850a7aa
2 changed files with 22 additions and 5 deletions

View File

@ -7,6 +7,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/pem" "encoding/pem"
"fmt" "fmt"
"math"
"net" "net"
"os" "os"
"strconv" "strconv"
@ -42,6 +43,7 @@ type TuicOption struct {
MaxUdpRelayPacketSize int `proxy:"max-udp-relay-packet-size,omitempty"` MaxUdpRelayPacketSize int `proxy:"max-udp-relay-packet-size,omitempty"`
FastOpen bool `proxy:"fast-open,omitempty"` FastOpen bool `proxy:"fast-open,omitempty"`
MaxOpenStreams int `proxy:"max-open-streams,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"` Fingerprint string `proxy:"fingerprint,omitempty"`
CustomCA string `proxy:"ca,omitempty"` CustomCA string `proxy:"ca,omitempty"`
@ -148,11 +150,20 @@ func NewTuic(option TuicOption) (*Tuic, error) {
option.MaxUdpRelayPacketSize = 1500 option.MaxUdpRelayPacketSize = 1500
} }
if option.MaxOpenStreams == 0 {
option.MaxOpenStreams = 100
}
// ensure server's incoming stream can handle correctly, increase to 1.1x
quicMaxOpenStreams := int64(option.MaxOpenStreams)
quicMaxOpenStreams = quicMaxOpenStreams + int64(math.Ceil(float64(quicMaxOpenStreams)/10.0))
quicConfig := &quic.Config{ quicConfig := &quic.Config{
InitialStreamReceiveWindow: uint64(option.ReceiveWindowConn), InitialStreamReceiveWindow: uint64(option.ReceiveWindowConn),
MaxStreamReceiveWindow: uint64(option.ReceiveWindowConn), MaxStreamReceiveWindow: uint64(option.ReceiveWindowConn),
InitialConnectionReceiveWindow: uint64(option.ReceiveWindow), InitialConnectionReceiveWindow: uint64(option.ReceiveWindow),
MaxConnectionReceiveWindow: uint64(option.ReceiveWindow), MaxConnectionReceiveWindow: uint64(option.ReceiveWindow),
MaxIncomingStreams: quicMaxOpenStreams,
MaxIncomingUniStreams: quicMaxOpenStreams,
KeepAlivePeriod: time.Duration(option.HeartbeatInterval) * time.Millisecond, KeepAlivePeriod: time.Duration(option.HeartbeatInterval) * time.Millisecond,
DisablePathMTUDiscovery: option.DisableMTUDiscovery, DisablePathMTUDiscovery: option.DisableMTUDiscovery,
EnableDatagrams: true, EnableDatagrams: true,
@ -186,6 +197,12 @@ func NewTuic(option TuicOption) (*Tuic, error) {
prefer: C.NewDNSPrefer(option.IPVersion), prefer: C.NewDNSPrefer(option.IPVersion),
}, },
} }
// to avoid tuic's "too many open streams", decrease to 0.9x
clientMaxOpenStreams := int64(option.MaxOpenStreams)
clientMaxOpenStreams = clientMaxOpenStreams - int64(math.Ceil(float64(clientMaxOpenStreams)/10.0))
if clientMaxOpenStreams < 1 {
clientMaxOpenStreams = 1
}
clientOption := &tuic.ClientOption{ clientOption := &tuic.ClientOption{
DialFn: t.dial, DialFn: t.dial,
TlsConfig: tlsConfig, TlsConfig: tlsConfig,
@ -198,6 +215,7 @@ func NewTuic(option TuicOption) (*Tuic, error) {
RequestTimeout: option.RequestTimeout, RequestTimeout: option.RequestTimeout,
MaxUdpRelayPacketSize: option.MaxUdpRelayPacketSize, MaxUdpRelayPacketSize: option.MaxUdpRelayPacketSize,
FastOpen: option.FastOpen, FastOpen: option.FastOpen,
MaxOpenStreams: clientMaxOpenStreams,
} }
t.client = tuic.NewClientPool(clientOption) t.client = tuic.NewClientPool(clientOption)

View File

@ -28,8 +28,6 @@ var (
TooManyOpenStreams = errors.New("tuic: too many open streams") TooManyOpenStreams = errors.New("tuic: too many open streams")
) )
const MaxOpenStreams = 100 - 90
type ClientOption struct { type ClientOption struct {
DialFn func(ctx context.Context, opts ...dialer.Option) (pc net.PacketConn, addr net.Addr, err error) DialFn func(ctx context.Context, opts ...dialer.Option) (pc net.PacketConn, addr net.Addr, err error)
@ -43,6 +41,7 @@ type ClientOption struct {
RequestTimeout int RequestTimeout int
MaxUdpRelayPacketSize int MaxUdpRelayPacketSize int
FastOpen bool FastOpen bool
MaxOpenStreams int64
} }
type Client struct { type Client struct {
@ -52,7 +51,7 @@ type Client struct {
quicConn quic.Connection quicConn quic.Connection
connMutex sync.Mutex connMutex sync.Mutex
openStreams atomic.Int32 openStreams atomic.Int64
udpInputMap sync.Map udpInputMap sync.Map
@ -255,7 +254,7 @@ func (t *Client) DialContext(ctx context.Context, metadata *C.Metadata) (net.Con
return nil, err return nil, err
} }
openStreams := t.openStreams.Add(1) openStreams := t.openStreams.Add(1)
if openStreams >= MaxOpenStreams { if openStreams >= t.MaxOpenStreams {
t.openStreams.Add(-1) t.openStreams.Add(-1)
return nil, TooManyOpenStreams return nil, TooManyOpenStreams
} }
@ -396,7 +395,7 @@ func (t *Client) ListenPacketContext(ctx context.Context, metadata *C.Metadata)
return nil, err return nil, err
} }
openStreams := t.openStreams.Add(1) openStreams := t.openStreams.Add(1)
if openStreams >= MaxOpenStreams { if openStreams >= t.MaxOpenStreams {
t.openStreams.Add(-1) t.openStreams.Add(-1)
return nil, TooManyOpenStreams return nil, TooManyOpenStreams
} }