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/pem"
"fmt"
"math"
"net"
"os"
"strconv"
@ -42,6 +43,7 @@ type TuicOption struct {
MaxUdpRelayPacketSize int `proxy:"max-udp-relay-packet-size,omitempty"`
FastOpen bool `proxy:"fast-open,omitempty"`
MaxOpenStreams int `proxy:"max-open-streams,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
CustomCA string `proxy:"ca,omitempty"`
@ -148,11 +150,20 @@ func NewTuic(option TuicOption) (*Tuic, error) {
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{
InitialStreamReceiveWindow: uint64(option.ReceiveWindowConn),
MaxStreamReceiveWindow: uint64(option.ReceiveWindowConn),
InitialConnectionReceiveWindow: uint64(option.ReceiveWindow),
MaxConnectionReceiveWindow: uint64(option.ReceiveWindow),
MaxIncomingStreams: quicMaxOpenStreams,
MaxIncomingUniStreams: quicMaxOpenStreams,
KeepAlivePeriod: time.Duration(option.HeartbeatInterval) * time.Millisecond,
DisablePathMTUDiscovery: option.DisableMTUDiscovery,
EnableDatagrams: true,
@ -186,6 +197,12 @@ func NewTuic(option TuicOption) (*Tuic, error) {
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{
DialFn: t.dial,
TlsConfig: tlsConfig,
@ -198,6 +215,7 @@ func NewTuic(option TuicOption) (*Tuic, error) {
RequestTimeout: option.RequestTimeout,
MaxUdpRelayPacketSize: option.MaxUdpRelayPacketSize,
FastOpen: option.FastOpen,
MaxOpenStreams: clientMaxOpenStreams,
}
t.client = tuic.NewClientPool(clientOption)

View file

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