forked from quic-go/quic-go
move the max flow control increments out of the params negotiator
The params negotiator was just keeping track of the value set in the quic.Config. The max flow control increments are not subject to negotiation, but an independent implementation decision of every peer.
This commit is contained in:
@@ -13,8 +13,9 @@ import (
|
||||
)
|
||||
|
||||
type flowControlManager struct {
|
||||
connParams handshake.ParamsNegotiator
|
||||
rttStats *congestion.RTTStats
|
||||
connParams handshake.ParamsNegotiator
|
||||
rttStats *congestion.RTTStats
|
||||
maxReceiveStreamWindow protocol.ByteCount
|
||||
|
||||
streamFlowController map[protocol.StreamID]*flowController
|
||||
connFlowController *flowController
|
||||
@@ -26,12 +27,18 @@ var _ FlowControlManager = &flowControlManager{}
|
||||
var errMapAccess = errors.New("Error accessing the flowController map.")
|
||||
|
||||
// NewFlowControlManager creates a new flow control manager
|
||||
func NewFlowControlManager(connParams handshake.ParamsNegotiator, rttStats *congestion.RTTStats) FlowControlManager {
|
||||
func NewFlowControlManager(
|
||||
connParams handshake.ParamsNegotiator,
|
||||
maxReceiveStreamWindow protocol.ByteCount,
|
||||
maxReceiveConnectionWindow protocol.ByteCount,
|
||||
rttStats *congestion.RTTStats,
|
||||
) FlowControlManager {
|
||||
return &flowControlManager{
|
||||
connParams: connParams,
|
||||
rttStats: rttStats,
|
||||
streamFlowController: make(map[protocol.StreamID]*flowController),
|
||||
connFlowController: newFlowController(0, false, connParams, rttStats),
|
||||
connParams: connParams,
|
||||
rttStats: rttStats,
|
||||
maxReceiveStreamWindow: maxReceiveStreamWindow,
|
||||
streamFlowController: make(map[protocol.StreamID]*flowController),
|
||||
connFlowController: newFlowController(0, false, connParams, maxReceiveConnectionWindow, rttStats),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +51,7 @@ func (f *flowControlManager) NewStream(streamID protocol.StreamID, contributesTo
|
||||
if _, ok := f.streamFlowController[streamID]; ok {
|
||||
return
|
||||
}
|
||||
|
||||
f.streamFlowController[streamID] = newFlowController(streamID, contributesToConnection, f.connParams, f.rttStats)
|
||||
f.streamFlowController[streamID] = newFlowController(streamID, contributesToConnection, f.connParams, f.maxReceiveStreamWindow, f.rttStats)
|
||||
}
|
||||
|
||||
// RemoveStream removes a closed stream from flow control
|
||||
|
||||
@@ -18,9 +18,7 @@ var _ = Describe("Flow Control Manager", func() {
|
||||
mockPn := mocks.NewMockParamsNegotiator(mockCtrl)
|
||||
mockPn.EXPECT().GetReceiveStreamFlowControlWindow().AnyTimes().Return(protocol.ByteCount(100))
|
||||
mockPn.EXPECT().GetReceiveConnectionFlowControlWindow().AnyTimes().Return(protocol.ByteCount(200))
|
||||
mockPn.EXPECT().GetMaxReceiveStreamFlowControlWindow().AnyTimes().Return(protocol.MaxByteCount)
|
||||
mockPn.EXPECT().GetMaxReceiveConnectionFlowControlWindow().AnyTimes().Return(protocol.MaxByteCount)
|
||||
fcm = NewFlowControlManager(mockPn, &congestion.RTTStats{}).(*flowControlManager)
|
||||
fcm = NewFlowControlManager(mockPn, protocol.MaxByteCount, protocol.MaxByteCount, &congestion.RTTStats{}).(*flowControlManager)
|
||||
})
|
||||
|
||||
It("creates a connection level flow controller", func() {
|
||||
|
||||
@@ -33,22 +33,27 @@ type flowController struct {
|
||||
var ErrReceivedSmallerByteOffset = errors.New("Received a smaller byte offset")
|
||||
|
||||
// newFlowController gets a new flow controller
|
||||
func newFlowController(streamID protocol.StreamID, contributesToConnection bool, connParams handshake.ParamsNegotiator, rttStats *congestion.RTTStats) *flowController {
|
||||
func newFlowController(
|
||||
streamID protocol.StreamID,
|
||||
contributesToConnection bool,
|
||||
connParams handshake.ParamsNegotiator,
|
||||
maxReceiveWindow protocol.ByteCount,
|
||||
rttStats *congestion.RTTStats,
|
||||
) *flowController {
|
||||
fc := flowController{
|
||||
streamID: streamID,
|
||||
contributesToConnection: contributesToConnection,
|
||||
connParams: connParams,
|
||||
rttStats: rttStats,
|
||||
streamID: streamID,
|
||||
contributesToConnection: contributesToConnection,
|
||||
connParams: connParams,
|
||||
rttStats: rttStats,
|
||||
maxReceiveWindowIncrement: maxReceiveWindow,
|
||||
}
|
||||
|
||||
if streamID == 0 {
|
||||
fc.receiveWindow = connParams.GetReceiveConnectionFlowControlWindow()
|
||||
fc.receiveWindowIncrement = fc.receiveWindow
|
||||
fc.maxReceiveWindowIncrement = connParams.GetMaxReceiveConnectionFlowControlWindow()
|
||||
} else {
|
||||
fc.receiveWindow = connParams.GetReceiveStreamFlowControlWindow()
|
||||
fc.receiveWindowIncrement = fc.receiveWindow
|
||||
fc.maxReceiveWindowIncrement = connParams.GetMaxReceiveStreamFlowControlWindow()
|
||||
}
|
||||
|
||||
return &fc
|
||||
|
||||
@@ -22,45 +22,46 @@ var _ = Describe("Flow controller", func() {
|
||||
var rttStats *congestion.RTTStats
|
||||
var mockPn *mocks.MockParamsNegotiator
|
||||
|
||||
maxReceiveStreamWindow := protocol.ByteCount(8000)
|
||||
maxReceiveConnectionWindow := protocol.ByteCount(9000)
|
||||
|
||||
BeforeEach(func() {
|
||||
mockPn = mocks.NewMockParamsNegotiator(mockCtrl)
|
||||
mockPn.EXPECT().GetSendStreamFlowControlWindow().AnyTimes().Return(protocol.ByteCount(1000))
|
||||
mockPn.EXPECT().GetReceiveStreamFlowControlWindow().AnyTimes().Return(protocol.ByteCount(2000))
|
||||
mockPn.EXPECT().GetSendConnectionFlowControlWindow().AnyTimes().Return(protocol.ByteCount(3000))
|
||||
mockPn.EXPECT().GetReceiveConnectionFlowControlWindow().AnyTimes().Return(protocol.ByteCount(4000))
|
||||
mockPn.EXPECT().GetMaxReceiveStreamFlowControlWindow().AnyTimes().Return(protocol.ByteCount(8000))
|
||||
mockPn.EXPECT().GetMaxReceiveConnectionFlowControlWindow().AnyTimes().Return(protocol.ByteCount(9000))
|
||||
rttStats = &congestion.RTTStats{}
|
||||
})
|
||||
|
||||
It("reads the stream send and receive windows when acting as stream-level flow controller", func() {
|
||||
fc := newFlowController(5, true, mockPn, rttStats)
|
||||
fc := newFlowController(5, true, mockPn, maxReceiveStreamWindow, rttStats)
|
||||
Expect(fc.streamID).To(Equal(protocol.StreamID(5)))
|
||||
Expect(fc.receiveWindow).To(Equal(protocol.ByteCount(2000)))
|
||||
Expect(fc.maxReceiveWindowIncrement).To(Equal(mockPn.GetMaxReceiveStreamFlowControlWindow()))
|
||||
Expect(fc.maxReceiveWindowIncrement).To(Equal(maxReceiveStreamWindow))
|
||||
})
|
||||
|
||||
It("reads the stream send and receive windows when acting as connection-level flow controller", func() {
|
||||
fc := newFlowController(0, false, mockPn, rttStats)
|
||||
fc := newFlowController(0, false, mockPn, maxReceiveConnectionWindow, rttStats)
|
||||
Expect(fc.streamID).To(Equal(protocol.StreamID(0)))
|
||||
Expect(fc.receiveWindow).To(Equal(protocol.ByteCount(4000)))
|
||||
Expect(fc.maxReceiveWindowIncrement).To(Equal(mockPn.GetMaxReceiveConnectionFlowControlWindow()))
|
||||
Expect(fc.maxReceiveWindowIncrement).To(Equal(maxReceiveConnectionWindow))
|
||||
})
|
||||
|
||||
It("does not set the stream flow control windows for sending", func() {
|
||||
fc := newFlowController(5, true, mockPn, rttStats)
|
||||
fc := newFlowController(5, true, mockPn, protocol.MaxByteCount, rttStats)
|
||||
Expect(fc.sendWindow).To(BeZero())
|
||||
})
|
||||
|
||||
It("does not set the connection flow control windows for sending", func() {
|
||||
fc := newFlowController(0, false, mockPn, rttStats)
|
||||
fc := newFlowController(0, false, mockPn, protocol.MaxByteCount, rttStats)
|
||||
Expect(fc.sendWindow).To(BeZero())
|
||||
})
|
||||
|
||||
It("says if it contributes to connection-level flow control", func() {
|
||||
fc := newFlowController(1, false, mockPn, rttStats)
|
||||
fc := newFlowController(1, false, mockPn, protocol.MaxByteCount, rttStats)
|
||||
Expect(fc.ContributesToConnection()).To(BeFalse())
|
||||
fc = newFlowController(5, true, mockPn, rttStats)
|
||||
fc = newFlowController(5, true, mockPn, protocol.MaxByteCount, rttStats)
|
||||
Expect(fc.ContributesToConnection()).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -114,11 +114,7 @@ var _ = Describe("Client Crypto Setup", func() {
|
||||
0,
|
||||
version,
|
||||
nil,
|
||||
&TransportParameters{
|
||||
MaxReceiveStreamFlowControlWindow: protocol.DefaultMaxReceiveStreamFlowControlWindowClient,
|
||||
MaxReceiveConnectionFlowControlWindow: protocol.DefaultMaxReceiveConnectionFlowControlWindowClient,
|
||||
IdleTimeout: protocol.DefaultIdleTimeout,
|
||||
},
|
||||
&TransportParameters{IdleTimeout: protocol.DefaultIdleTimeout},
|
||||
aeadChanged,
|
||||
nil,
|
||||
)
|
||||
|
||||
@@ -202,11 +202,7 @@ var _ = Describe("Server Crypto Setup", func() {
|
||||
remoteAddr,
|
||||
version,
|
||||
scfg,
|
||||
&TransportParameters{
|
||||
MaxReceiveStreamFlowControlWindow: protocol.DefaultMaxReceiveStreamFlowControlWindowServer,
|
||||
MaxReceiveConnectionFlowControlWindow: protocol.DefaultMaxReceiveConnectionFlowControlWindowServer,
|
||||
IdleTimeout: protocol.DefaultIdleTimeout,
|
||||
},
|
||||
&TransportParameters{IdleTimeout: protocol.DefaultIdleTimeout},
|
||||
supportedVersions,
|
||||
nil,
|
||||
aeadChanged,
|
||||
|
||||
@@ -28,8 +28,6 @@ type CryptoSetup interface {
|
||||
|
||||
// TransportParameters are parameters sent to the peer during the handshake
|
||||
type TransportParameters struct {
|
||||
RequestConnectionIDOmission bool
|
||||
MaxReceiveStreamFlowControlWindow protocol.ByteCount
|
||||
MaxReceiveConnectionFlowControlWindow protocol.ByteCount
|
||||
IdleTimeout time.Duration
|
||||
RequestConnectionIDOmission bool
|
||||
IdleTimeout time.Duration
|
||||
}
|
||||
|
||||
@@ -14,9 +14,7 @@ type ParamsNegotiator interface {
|
||||
GetSendStreamFlowControlWindow() protocol.ByteCount
|
||||
GetSendConnectionFlowControlWindow() protocol.ByteCount
|
||||
GetReceiveStreamFlowControlWindow() protocol.ByteCount
|
||||
GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount
|
||||
GetReceiveConnectionFlowControlWindow() protocol.ByteCount
|
||||
GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount
|
||||
GetMaxOutgoingStreams() uint32
|
||||
GetMaxIncomingStreams() uint32
|
||||
// get the idle timeout that was sent by the peer
|
||||
@@ -50,8 +48,6 @@ type paramsNegotiatorBase struct {
|
||||
sendConnectionFlowControlWindow protocol.ByteCount
|
||||
receiveStreamFlowControlWindow protocol.ByteCount
|
||||
receiveConnectionFlowControlWindow protocol.ByteCount
|
||||
maxReceiveStreamFlowControlWindow protocol.ByteCount
|
||||
maxReceiveConnectionFlowControlWindow protocol.ByteCount
|
||||
}
|
||||
|
||||
func (h *paramsNegotiatorBase) init(params *TransportParameters) {
|
||||
@@ -59,8 +55,6 @@ func (h *paramsNegotiatorBase) init(params *TransportParameters) {
|
||||
h.sendConnectionFlowControlWindow = protocol.InitialConnectionFlowControlWindow // can only be changed by the client
|
||||
h.receiveStreamFlowControlWindow = protocol.ReceiveStreamFlowControlWindow
|
||||
h.receiveConnectionFlowControlWindow = protocol.ReceiveConnectionFlowControlWindow
|
||||
h.maxReceiveStreamFlowControlWindow = params.MaxReceiveStreamFlowControlWindow
|
||||
h.maxReceiveConnectionFlowControlWindow = params.MaxReceiveConnectionFlowControlWindow
|
||||
h.requestConnectionIDOmission = params.RequestConnectionIDOmission
|
||||
|
||||
h.idleTimeout = params.IdleTimeout
|
||||
@@ -101,11 +95,6 @@ func (h *paramsNegotiatorBase) GetReceiveStreamFlowControlWindow() protocol.Byte
|
||||
return h.receiveStreamFlowControlWindow
|
||||
}
|
||||
|
||||
// GetMaxReceiveStreamFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
|
||||
func (h *paramsNegotiatorBase) GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount {
|
||||
return h.maxReceiveStreamFlowControlWindow
|
||||
}
|
||||
|
||||
// GetReceiveConnectionFlowControlWindow gets the size of the stream-level flow control window for receiving data
|
||||
func (h *paramsNegotiatorBase) GetReceiveConnectionFlowControlWindow() protocol.ByteCount {
|
||||
h.mutex.RLock()
|
||||
@@ -113,10 +102,6 @@ func (h *paramsNegotiatorBase) GetReceiveConnectionFlowControlWindow() protocol.
|
||||
return h.receiveConnectionFlowControlWindow
|
||||
}
|
||||
|
||||
func (h *paramsNegotiatorBase) GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount {
|
||||
return h.maxReceiveConnectionFlowControlWindow
|
||||
}
|
||||
|
||||
func (h *paramsNegotiatorBase) GetMaxOutgoingStreams() uint32 {
|
||||
h.mutex.RLock()
|
||||
defer h.mutex.RUnlock()
|
||||
|
||||
@@ -2,7 +2,6 @@ package handshake
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
@@ -13,29 +12,20 @@ import (
|
||||
var _ = Describe("Params Negotiator (for gQUIC)", func() {
|
||||
var pn *paramsNegotiatorGQUIC // a connectionParametersManager for a server
|
||||
var pnClient *paramsNegotiatorGQUIC
|
||||
const MB = 1 << 20
|
||||
maxReceiveStreamFlowControlWindowServer := protocol.ByteCount(math.Floor(1.1 * MB)) // default is 1 MB
|
||||
maxReceiveConnectionFlowControlWindowServer := protocol.ByteCount(math.Floor(1.5 * MB)) // default is 1.5 MB
|
||||
maxReceiveStreamFlowControlWindowClient := protocol.ByteCount(math.Floor(6.4 * MB)) // default is 6 MB
|
||||
maxReceiveConnectionFlowControlWindowClient := protocol.ByteCount(math.Floor(13 * MB)) // default is 15 MB
|
||||
idleTimeout := 42 * time.Second
|
||||
BeforeEach(func() {
|
||||
pn = newParamsNegotiatorGQUIC(
|
||||
protocol.PerspectiveServer,
|
||||
protocol.VersionWhatever,
|
||||
&TransportParameters{
|
||||
MaxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindowServer,
|
||||
MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindowServer,
|
||||
IdleTimeout: idleTimeout,
|
||||
IdleTimeout: idleTimeout,
|
||||
},
|
||||
)
|
||||
pnClient = newParamsNegotiatorGQUIC(
|
||||
protocol.PerspectiveClient,
|
||||
protocol.VersionWhatever,
|
||||
&TransportParameters{
|
||||
MaxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindowClient,
|
||||
MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindowClient,
|
||||
IdleTimeout: idleTimeout,
|
||||
IdleTimeout: idleTimeout,
|
||||
},
|
||||
)
|
||||
})
|
||||
@@ -158,13 +148,6 @@ var _ = Describe("Params Negotiator (for gQUIC)", func() {
|
||||
Expect(pnClient.GetReceiveConnectionFlowControlWindow()).To(BeEquivalentTo(protocol.ReceiveConnectionFlowControlWindow))
|
||||
})
|
||||
|
||||
It("has the correct maximum flow control windows", func() {
|
||||
Expect(pn.GetMaxReceiveStreamFlowControlWindow()).To(Equal(maxReceiveStreamFlowControlWindowServer))
|
||||
Expect(pn.GetMaxReceiveConnectionFlowControlWindow()).To(Equal(maxReceiveConnectionFlowControlWindowServer))
|
||||
Expect(pnClient.GetMaxReceiveStreamFlowControlWindow()).To(Equal(maxReceiveStreamFlowControlWindowClient))
|
||||
Expect(pnClient.GetMaxReceiveConnectionFlowControlWindow()).To(Equal(maxReceiveConnectionFlowControlWindowClient))
|
||||
})
|
||||
|
||||
It("sets a new stream-level flow control window for sending", func() {
|
||||
values := map[Tag][]byte{TagSFCW: {0xDE, 0xAD, 0xBE, 0xEF}}
|
||||
err := pn.SetFromMap(values)
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
protocol "github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
reflect "reflect"
|
||||
time "time"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
protocol "github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
// MockParamsNegotiator is a mock of ParamsNegotiator interface
|
||||
@@ -70,18 +71,6 @@ func (mr *MockParamsNegotiatorMockRecorder) GetReceiveStreamFlowControlWindow()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceiveStreamFlowControlWindow", reflect.TypeOf((*MockParamsNegotiator)(nil).GetReceiveStreamFlowControlWindow))
|
||||
}
|
||||
|
||||
// GetMaxReceiveStreamFlowControlWindow mocks base method
|
||||
func (m *MockParamsNegotiator) GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount {
|
||||
ret := m.ctrl.Call(m, "GetMaxReceiveStreamFlowControlWindow")
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetMaxReceiveStreamFlowControlWindow indicates an expected call of GetMaxReceiveStreamFlowControlWindow
|
||||
func (mr *MockParamsNegotiatorMockRecorder) GetMaxReceiveStreamFlowControlWindow() *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMaxReceiveStreamFlowControlWindow", reflect.TypeOf((*MockParamsNegotiator)(nil).GetMaxReceiveStreamFlowControlWindow))
|
||||
}
|
||||
|
||||
// GetReceiveConnectionFlowControlWindow mocks base method
|
||||
func (m *MockParamsNegotiator) GetReceiveConnectionFlowControlWindow() protocol.ByteCount {
|
||||
ret := m.ctrl.Call(m, "GetReceiveConnectionFlowControlWindow")
|
||||
@@ -94,18 +83,6 @@ func (mr *MockParamsNegotiatorMockRecorder) GetReceiveConnectionFlowControlWindo
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceiveConnectionFlowControlWindow", reflect.TypeOf((*MockParamsNegotiator)(nil).GetReceiveConnectionFlowControlWindow))
|
||||
}
|
||||
|
||||
// GetMaxReceiveConnectionFlowControlWindow mocks base method
|
||||
func (m *MockParamsNegotiator) GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount {
|
||||
ret := m.ctrl.Call(m, "GetMaxReceiveConnectionFlowControlWindow")
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetMaxReceiveConnectionFlowControlWindow indicates an expected call of GetMaxReceiveConnectionFlowControlWindow
|
||||
func (mr *MockParamsNegotiatorMockRecorder) GetMaxReceiveConnectionFlowControlWindow() *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMaxReceiveConnectionFlowControlWindow", reflect.TypeOf((*MockParamsNegotiator)(nil).GetMaxReceiveConnectionFlowControlWindow))
|
||||
}
|
||||
|
||||
// GetMaxOutgoingStreams mocks base method
|
||||
func (m *MockParamsNegotiator) GetMaxOutgoingStreams() uint32 {
|
||||
ret := m.ctrl.Call(m, "GetMaxOutgoingStreams")
|
||||
|
||||
Reference in New Issue
Block a user