diff --git a/config.go b/config.go index fbd6da17..59df4cfd 100644 --- a/config.go +++ b/config.go @@ -1,13 +1,13 @@ package quic import ( - "errors" "fmt" "net" "time" "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/utils" + "github.com/quic-go/quic-go/quicvarint" ) // Clone clones a Config @@ -24,11 +24,18 @@ func validateConfig(config *Config) error { if config == nil { return nil } - if config.MaxIncomingStreams > 1<<60 { - return errors.New("invalid value for Config.MaxIncomingStreams") + const maxStreams = 1 << 60 + if config.MaxIncomingStreams > maxStreams { + config.MaxIncomingStreams = maxStreams } - if config.MaxIncomingUniStreams > 1<<60 { - return errors.New("invalid value for Config.MaxIncomingUniStreams") + if config.MaxIncomingUniStreams > maxStreams { + config.MaxIncomingUniStreams = maxStreams + } + if config.MaxStreamReceiveWindow > quicvarint.Max { + config.MaxStreamReceiveWindow = quicvarint.Max + } + if config.MaxConnectionReceiveWindow > quicvarint.Max { + config.MaxConnectionReceiveWindow = quicvarint.Max } // check that all QUIC versions are actually supported for _, v := range config.Versions { diff --git a/config_test.go b/config_test.go index 53482ca4..1eca3d5d 100644 --- a/config_test.go +++ b/config_test.go @@ -10,6 +10,7 @@ import ( "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/logging" + "github.com/quic-go/quic-go/quicvarint" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -22,15 +23,33 @@ var _ = Describe("Config", func() { }) It("validates a config with normal values", func() { - Expect(validateConfig(populateServerConfig(&Config{}))).To(Succeed()) + conf := populateServerConfig(&Config{ + MaxIncomingStreams: 5, + MaxStreamReceiveWindow: 10, + }) + Expect(validateConfig(conf)).To(Succeed()) + Expect(conf.MaxIncomingStreams).To(BeEquivalentTo(5)) + Expect(conf.MaxStreamReceiveWindow).To(BeEquivalentTo(10)) }) - It("errors on too large values for MaxIncomingStreams", func() { - Expect(validateConfig(&Config{MaxIncomingStreams: 1<<60 + 1})).To(MatchError("invalid value for Config.MaxIncomingStreams")) + It("clips too large values for the stream limits", func() { + conf := &Config{ + MaxIncomingStreams: 1<<60 + 1, + MaxIncomingUniStreams: 1<<60 + 2, + } + Expect(validateConfig(conf)).To(Succeed()) + Expect(conf.MaxIncomingStreams).To(BeEquivalentTo(int64(1 << 60))) + Expect(conf.MaxIncomingUniStreams).To(BeEquivalentTo(int64(1 << 60))) }) - It("errors on too large values for MaxIncomingUniStreams", func() { - Expect(validateConfig(&Config{MaxIncomingUniStreams: 1<<60 + 1})).To(MatchError("invalid value for Config.MaxIncomingUniStreams")) + It("clips too large values for the flow control windows", func() { + conf := &Config{ + MaxStreamReceiveWindow: quicvarint.Max + 1, + MaxConnectionReceiveWindow: quicvarint.Max + 2, + } + Expect(validateConfig(conf)).To(Succeed()) + Expect(conf.MaxStreamReceiveWindow).To(BeEquivalentTo(uint64(quicvarint.Max))) + Expect(conf.MaxConnectionReceiveWindow).To(BeEquivalentTo(uint64(quicvarint.Max))) }) }) diff --git a/interface.go b/interface.go index cdab015b..d98807b1 100644 --- a/interface.go +++ b/interface.go @@ -276,17 +276,21 @@ type Config struct { // If the application is consuming data quickly enough, the flow control auto-tuning algorithm // will increase the window up to MaxStreamReceiveWindow. // If this value is zero, it will default to 512 KB. + // Values larger than the maximum varint (quicvarint.Max) will be clipped to that value. InitialStreamReceiveWindow uint64 // MaxStreamReceiveWindow is the maximum stream-level flow control window for receiving data. // If this value is zero, it will default to 6 MB. + // Values larger than the maximum varint (quicvarint.Max) will be clipped to that value. MaxStreamReceiveWindow uint64 // InitialConnectionReceiveWindow is the initial size of the stream-level flow control window for receiving data. // If the application is consuming data quickly enough, the flow control auto-tuning algorithm // will increase the window up to MaxConnectionReceiveWindow. // If this value is zero, it will default to 512 KB. + // Values larger than the maximum varint (quicvarint.Max) will be clipped to that value. InitialConnectionReceiveWindow uint64 // MaxConnectionReceiveWindow is the connection-level flow control window for receiving data. // If this value is zero, it will default to 15 MB. + // Values larger than the maximum varint (quicvarint.Max) will be clipped to that value. MaxConnectionReceiveWindow uint64 // AllowConnectionWindowIncrease is called every time the connection flow controller attempts // to increase the connection flow control window. @@ -296,14 +300,14 @@ type Config struct { // in this callback. AllowConnectionWindowIncrease func(conn Connection, delta uint64) bool // MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open. - // Values above 2^60 are invalid. // If not set, it will default to 100. // If set to a negative value, it doesn't allow any bidirectional streams. + // Values larger than 2^60 will be clipped to that value. MaxIncomingStreams int64 // MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open. - // Values above 2^60 are invalid. // If not set, it will default to 100. // If set to a negative value, it doesn't allow any unidirectional streams. + // Values larger than 2^60 will be clipped to that value. MaxIncomingUniStreams int64 // KeepAlivePeriod defines whether this peer will periodically send a packet to keep the connection alive. // If set to 0, then no keep alive is sent. Otherwise, the keep alive is sent on that period (or at most