release connection-level flow control credit when a stream is reset

This commit is contained in:
Marten Seemann
2019-01-22 23:45:40 +07:00
parent 1864e301ef
commit 1d7d532035
5 changed files with 99 additions and 26 deletions

View File

@@ -18,8 +18,12 @@ type StreamFlowController interface {
flowController
// for receiving
// UpdateHighestReceived should be 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
// 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
UpdateHighestReceived(offset protocol.ByteCount, final bool) error
// Abandon should be called when reading from the stream is aborted early,
// and there won't be any further calls to AddBytesRead.
Abandon()
}
// The ConnectionFlowController is the flow controller for the connection.

View File

@@ -93,6 +93,12 @@ func (c *streamFlowController) AddBytesRead(n protocol.ByteCount) {
c.connection.AddBytesRead(n)
}
func (c *streamFlowController) Abandon() {
if unread := c.highestReceived - c.bytesRead; unread > 0 {
c.connection.AddBytesRead(unread)
}
}
func (c *streamFlowController) AddBytesSent(n protocol.ByteCount) {
c.baseFlowController.AddBytesSent(n)
c.connection.AddBytesSent(n)

View File

@@ -149,6 +149,13 @@ var _ = Describe("Stream Flow controller", func() {
err = controller.UpdateHighestReceived(201, true)
Expect(err).To(MatchError("StreamDataAfterTermination: Received inconsistent final offset for stream 10 (old: 200, new: 201 bytes)"))
})
It("tells the connection flow controller when a stream is abandoned", func() {
controller.AddBytesRead(5)
Expect(controller.UpdateHighestReceived(100, true)).To(Succeed())
controller.Abandon()
Expect(controller.connection.(*connectionFlowController).bytesRead).To(Equal(protocol.ByteCount(100)))
})
})
It("saves when data is read", func() {
@@ -198,6 +205,13 @@ var _ = Describe("Stream Flow controller", func() {
Expect(controller.connection.(*connectionFlowController).receiveWindowSize).To(Equal(protocol.ByteCount(float64(controller.receiveWindowSize) * protocol.ConnectionFlowControlMultiplier)))
})
It("sends a connection-level window update when a large stream is abandoned", func() {
Expect(controller.UpdateHighestReceived(90, true)).To(Succeed())
Expect(controller.connection.GetWindowUpdate()).To(BeZero())
controller.Abandon()
Expect(controller.connection.GetWindowUpdate()).ToNot(BeZero())
})
It("doesn't increase the window after a final offset was already received", func() {
Expect(controller.UpdateHighestReceived(90, true)).To(Succeed())
controller.AddBytesRead(30)