forked from quic-go/quic-go
reliably queue MAX_DATA frames (#4844)
This commit is contained in:
@@ -57,10 +57,12 @@ func (c *connectionFlowController) IncrementHighestReceived(increment protocol.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *connectionFlowController) AddBytesRead(n protocol.ByteCount) {
|
||||
func (c *connectionFlowController) AddBytesRead(n protocol.ByteCount) (hasWindowUpdate bool) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
c.baseFlowController.addBytesRead(n)
|
||||
c.mutex.Unlock()
|
||||
return c.baseFlowController.hasWindowUpdate()
|
||||
}
|
||||
|
||||
func (c *connectionFlowController) GetWindowUpdate(now time.Time) protocol.ByteCount {
|
||||
|
||||
@@ -19,8 +19,9 @@ func TestConnectionFlowControlWindowUpdate(t *testing.T) {
|
||||
&utils.RTTStats{},
|
||||
utils.DefaultLogger,
|
||||
)
|
||||
require.False(t, fc.AddBytesRead(1))
|
||||
require.Zero(t, fc.GetWindowUpdate(time.Now()))
|
||||
fc.AddBytesRead(100)
|
||||
require.True(t, fc.AddBytesRead(99))
|
||||
require.Equal(t, protocol.ByteCount(200), fc.GetWindowUpdate(time.Now()))
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ type flowController interface {
|
||||
// A StreamFlowController is a flow controller for a QUIC stream.
|
||||
type StreamFlowController interface {
|
||||
flowController
|
||||
AddBytesRead(protocol.ByteCount) (shouldQueueWindowUpdate bool)
|
||||
AddBytesRead(protocol.ByteCount) (hasStreamWindowUpdate, hasConnWindowUpdate bool)
|
||||
// UpdateHighestReceived is called when a new highest offset is received
|
||||
// final has to be to true if this is the final offset of the stream,
|
||||
// as contained in a STREAM frame with FIN bit, and the RESET_STREAM frame
|
||||
@@ -32,7 +32,7 @@ type StreamFlowController interface {
|
||||
// The ConnectionFlowController is the flow controller for the connection.
|
||||
type ConnectionFlowController interface {
|
||||
flowController
|
||||
AddBytesRead(protocol.ByteCount)
|
||||
AddBytesRead(protocol.ByteCount) (hasWindowUpdate bool)
|
||||
Reset() error
|
||||
IsNewlyBlocked() (bool, protocol.ByteCount)
|
||||
}
|
||||
|
||||
@@ -98,12 +98,12 @@ func (c *streamFlowController) UpdateHighestReceived(offset protocol.ByteCount,
|
||||
return c.connection.IncrementHighestReceived(increment, now)
|
||||
}
|
||||
|
||||
func (c *streamFlowController) AddBytesRead(n protocol.ByteCount) (shouldQueueWindowUpdate bool) {
|
||||
func (c *streamFlowController) AddBytesRead(n protocol.ByteCount) (hasStreamWindowUpdate, hasConnWindowUpdate bool) {
|
||||
c.mutex.Lock()
|
||||
c.baseFlowController.addBytesRead(n)
|
||||
shouldQueueWindowUpdate = c.shouldQueueWindowUpdate()
|
||||
hasStreamWindowUpdate = c.shouldQueueWindowUpdate()
|
||||
c.mutex.Unlock()
|
||||
c.connection.AddBytesRead(n)
|
||||
hasConnWindowUpdate = c.connection.AddBytesRead(n)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -192,16 +192,20 @@ func TestStreamWindowUpdate(t *testing.T) {
|
||||
utils.DefaultLogger,
|
||||
)
|
||||
require.Zero(t, fc.GetWindowUpdate(time.Now()))
|
||||
fc.AddBytesRead(24)
|
||||
hasStreamWindowUpdate, _ := fc.AddBytesRead(24)
|
||||
require.False(t, hasStreamWindowUpdate)
|
||||
require.Zero(t, fc.GetWindowUpdate(time.Now()))
|
||||
// the window is updated when it's 25% filled
|
||||
fc.AddBytesRead(1)
|
||||
hasStreamWindowUpdate, _ = fc.AddBytesRead(1)
|
||||
require.True(t, hasStreamWindowUpdate)
|
||||
require.Equal(t, protocol.ByteCount(125), fc.GetWindowUpdate(time.Now()))
|
||||
|
||||
fc.AddBytesRead(24)
|
||||
hasStreamWindowUpdate, _ = fc.AddBytesRead(24)
|
||||
require.False(t, hasStreamWindowUpdate)
|
||||
require.Zero(t, fc.GetWindowUpdate(time.Now()))
|
||||
// the window is updated when it's 25% filled
|
||||
fc.AddBytesRead(1)
|
||||
hasStreamWindowUpdate, _ = fc.AddBytesRead(1)
|
||||
require.True(t, hasStreamWindowUpdate)
|
||||
require.Equal(t, protocol.ByteCount(150), fc.GetWindowUpdate(time.Now()))
|
||||
|
||||
// Receive the final offset.
|
||||
@@ -211,6 +215,31 @@ func TestStreamWindowUpdate(t *testing.T) {
|
||||
require.Zero(t, fc.GetWindowUpdate(time.Now()))
|
||||
}
|
||||
|
||||
func TestStreamConnectionWindowUpdate(t *testing.T) {
|
||||
connFC := NewConnectionFlowController(
|
||||
100,
|
||||
protocol.MaxByteCount,
|
||||
nil,
|
||||
&utils.RTTStats{},
|
||||
utils.DefaultLogger,
|
||||
)
|
||||
fc := NewStreamFlowController(
|
||||
42,
|
||||
connFC,
|
||||
1000,
|
||||
protocol.MaxByteCount,
|
||||
protocol.MaxByteCount,
|
||||
&utils.RTTStats{},
|
||||
utils.DefaultLogger,
|
||||
)
|
||||
|
||||
hasStreamWindowUpdate, hasConnWindowUpdate := fc.AddBytesRead(50)
|
||||
require.False(t, hasStreamWindowUpdate)
|
||||
require.Zero(t, fc.GetWindowUpdate(time.Now()))
|
||||
require.True(t, hasConnWindowUpdate)
|
||||
require.NotZero(t, connFC.GetWindowUpdate(time.Now()))
|
||||
}
|
||||
|
||||
func TestStreamWindowAutoTuning(t *testing.T) {
|
||||
// the RTT is 1 second
|
||||
rttStats := &utils.RTTStats{}
|
||||
|
||||
@@ -42,9 +42,11 @@ func (m *MockConnectionFlowController) EXPECT() *MockConnectionFlowControllerMoc
|
||||
}
|
||||
|
||||
// AddBytesRead mocks base method.
|
||||
func (m *MockConnectionFlowController) AddBytesRead(arg0 protocol.ByteCount) {
|
||||
func (m *MockConnectionFlowController) AddBytesRead(arg0 protocol.ByteCount) bool {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "AddBytesRead", arg0)
|
||||
ret := m.ctrl.Call(m, "AddBytesRead", arg0)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AddBytesRead indicates an expected call of AddBytesRead.
|
||||
@@ -60,19 +62,19 @@ type MockConnectionFlowControllerAddBytesReadCall struct {
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockConnectionFlowControllerAddBytesReadCall) Return() *MockConnectionFlowControllerAddBytesReadCall {
|
||||
c.Call = c.Call.Return()
|
||||
func (c *MockConnectionFlowControllerAddBytesReadCall) Return(hasWindowUpdate bool) *MockConnectionFlowControllerAddBytesReadCall {
|
||||
c.Call = c.Call.Return(hasWindowUpdate)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockConnectionFlowControllerAddBytesReadCall) Do(f func(protocol.ByteCount)) *MockConnectionFlowControllerAddBytesReadCall {
|
||||
func (c *MockConnectionFlowControllerAddBytesReadCall) Do(f func(protocol.ByteCount) bool) *MockConnectionFlowControllerAddBytesReadCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockConnectionFlowControllerAddBytesReadCall) DoAndReturn(f func(protocol.ByteCount)) *MockConnectionFlowControllerAddBytesReadCall {
|
||||
func (c *MockConnectionFlowControllerAddBytesReadCall) DoAndReturn(f func(protocol.ByteCount) bool) *MockConnectionFlowControllerAddBytesReadCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -78,11 +78,12 @@ func (c *MockStreamFlowControllerAbandonCall) DoAndReturn(f func()) *MockStreamF
|
||||
}
|
||||
|
||||
// AddBytesRead mocks base method.
|
||||
func (m *MockStreamFlowController) AddBytesRead(arg0 protocol.ByteCount) bool {
|
||||
func (m *MockStreamFlowController) AddBytesRead(arg0 protocol.ByteCount) (bool, bool) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AddBytesRead", arg0)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
ret1, _ := ret[1].(bool)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AddBytesRead indicates an expected call of AddBytesRead.
|
||||
@@ -98,19 +99,19 @@ type MockStreamFlowControllerAddBytesReadCall struct {
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockStreamFlowControllerAddBytesReadCall) Return(shouldQueueWindowUpdate bool) *MockStreamFlowControllerAddBytesReadCall {
|
||||
c.Call = c.Call.Return(shouldQueueWindowUpdate)
|
||||
func (c *MockStreamFlowControllerAddBytesReadCall) Return(hasStreamWindowUpdate, hasConnWindowUpdate bool) *MockStreamFlowControllerAddBytesReadCall {
|
||||
c.Call = c.Call.Return(hasStreamWindowUpdate, hasConnWindowUpdate)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockStreamFlowControllerAddBytesReadCall) Do(f func(protocol.ByteCount) bool) *MockStreamFlowControllerAddBytesReadCall {
|
||||
func (c *MockStreamFlowControllerAddBytesReadCall) Do(f func(protocol.ByteCount) (bool, bool)) *MockStreamFlowControllerAddBytesReadCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockStreamFlowControllerAddBytesReadCall) DoAndReturn(f func(protocol.ByteCount) bool) *MockStreamFlowControllerAddBytesReadCall {
|
||||
func (c *MockStreamFlowControllerAddBytesReadCall) DoAndReturn(f func(protocol.ByteCount) (bool, bool)) *MockStreamFlowControllerAddBytesReadCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user