diff --git a/config.go b/config.go index 8e439c261..61c4097a6 100644 --- a/config.go +++ b/config.go @@ -110,6 +110,7 @@ func populateConfig(config *Config) *Config { MaxStreamReceiveWindow: maxStreamReceiveWindow, InitialConnectionReceiveWindow: initialConnectionReceiveWindow, MaxConnectionReceiveWindow: maxConnectionReceiveWindow, + AllowConnectionWindowIncrease: config.AllowConnectionWindowIncrease, MaxIncomingStreams: maxIncomingStreams, MaxIncomingUniStreams: maxIncomingUniStreams, ConnectionIDLength: config.ConnectionIDLength, diff --git a/config_test.go b/config_test.go index b8454b10a..4e815cbec 100644 --- a/config_test.go +++ b/config_test.go @@ -45,7 +45,7 @@ var _ = Describe("Config", func() { } switch fn := typ.Field(i).Name; fn { - case "AcceptToken", "GetLogWriter": + case "AcceptToken", "GetLogWriter", "AllowConnectionWindowIncrease": // Can't compare functions. case "Versions": f.Set(reflect.ValueOf([]VersionNumber{1, 2, 3})) @@ -100,13 +100,16 @@ var _ = Describe("Config", func() { Context("cloning", func() { It("clones function fields", func() { - var calledAcceptToken bool + var calledAcceptToken, calledAllowConnectionWindowIncrease bool c1 := &Config{ - AcceptToken: func(_ net.Addr, _ *Token) bool { calledAcceptToken = true; return true }, + AcceptToken: func(_ net.Addr, _ *Token) bool { calledAcceptToken = true; return true }, + AllowConnectionWindowIncrease: func(Session, int) bool { calledAllowConnectionWindowIncrease = true; return true }, } c2 := c1.Clone() c2.AcceptToken(&net.UDPAddr{}, &Token{}) Expect(calledAcceptToken).To(BeTrue()) + c2.AllowConnectionWindowIncrease(nil, 1234) + Expect(calledAllowConnectionWindowIncrease).To(BeTrue()) }) It("clones non-function fields", func() { diff --git a/interface.go b/interface.go index 3bec71fa7..fa53d7470 100644 --- a/interface.go +++ b/interface.go @@ -266,6 +266,11 @@ type Config struct { // MaxConnectionReceiveWindow is the connection-level flow control window for receiving data. // If this value is zero, it will default to 15 MB. MaxConnectionReceiveWindow uint64 + // AllowConnectionWindowIncrease is called every time the connection flow controller attempts + // to increase the connection flow control window. + // If set, the caller can prevent an increase of the window. Typically, it would do so to + // limit the memory usage. + AllowConnectionWindowIncrease func(sess Session, delta int) 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. diff --git a/session.go b/session.go index c2f6e65ed..2c8b23696 100644 --- a/session.go +++ b/session.go @@ -506,7 +506,12 @@ func (s *session) preSetup() { protocol.ByteCount(s.config.InitialConnectionReceiveWindow), protocol.ByteCount(s.config.MaxConnectionReceiveWindow), s.onHasConnectionWindowUpdate, - func(protocol.ByteCount) bool { return true }, + func(size protocol.ByteCount) bool { + if s.config.AllowConnectionWindowIncrease == nil { + return true + } + return s.config.AllowConnectionWindowIncrease(s, int(size)) + }, s.rttStats, s.logger, )