change fcm.SendWindowSize to include conn window to simplify framer

This commit is contained in:
Lucas Clemente
2016-07-26 17:06:54 +02:00
parent ebf41d9f26
commit 5f774c8e03
6 changed files with 49 additions and 39 deletions

View File

@@ -6,6 +6,7 @@ import (
"github.com/lucas-clemente/quic-go/handshake"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/utils"
)
type flowControlManager struct {
@@ -146,8 +147,17 @@ func (f *flowControlManager) SendWindowSize(streamID protocol.StreamID) (protoco
if err != nil {
return 0, err
}
res := streamFlowController.SendWindowSize()
return streamFlowController.SendWindowOffset(), nil
contributes, ok := f.contributesToConnectionFlowControl[streamID]
if !ok {
return 0, errMapAccess
}
if contributes {
res = utils.MinByteCount(res, f.streamFlowController[0].SendWindowSize())
}
return res, nil
}
func (f *flowControlManager) RemainingConnectionWindowSize() protocol.ByteCount {

View File

@@ -141,24 +141,37 @@ var _ = Describe("Flow Control Manager", func() {
Context("window sizes", func() {
It("gets the window size of a stream", func() {
fcm.NewStream(5, true)
fcm.NewStream(5, false)
updated, err := fcm.UpdateWindow(5, 0x1000)
Expect(err).ToNot(HaveOccurred())
Expect(updated).To(BeTrue())
fcm.AddBytesSent(5, 0x500) // WindowSize should return the same value no matter how much was sent
fcm.AddBytesSent(5, 0x500)
size, err := fcm.SendWindowSize(5)
Expect(err).ToNot(HaveOccurred())
Expect(size).To(Equal(protocol.ByteCount(0x1000)))
Expect(size).To(Equal(protocol.ByteCount(0x1000 - 0x500)))
})
It("gets the window size of a stream", func() {
It("gets the connection window size", func() {
fcm.NewStream(5, true)
updated, err := fcm.UpdateWindow(0, 0x1000)
Expect(err).ToNot(HaveOccurred())
Expect(updated).To(BeTrue())
fcm.AddBytesSent(5, 0x456) // WindowSize should return the same value no matter how much was sent
fcm.AddBytesSent(5, 0x500)
size := fcm.RemainingConnectionWindowSize()
Expect(size).To(Equal(protocol.ByteCount(0x1000 - 0x456)))
Expect(size).To(Equal(protocol.ByteCount(0x1000 - 0x500)))
})
It("limits the stream window size by the connection window size", func() {
fcm.NewStream(5, true)
updated, err := fcm.UpdateWindow(0, 0x500)
Expect(err).ToNot(HaveOccurred())
Expect(updated).To(BeTrue())
updated, err = fcm.UpdateWindow(5, 0x1000)
Expect(err).ToNot(HaveOccurred())
Expect(updated).To(BeTrue())
size, err := fcm.SendWindowSize(5)
Expect(err).NotTo(HaveOccurred())
Expect(size).To(Equal(protocol.ByteCount(0x500)))
})
It("does not reduce the size of the connection level window, if the stream does not contribute", func() {

View File

@@ -304,10 +304,10 @@ var _ = Describe("Session", func() {
Expect(err).ToNot(HaveOccurred())
err = session.handleWindowUpdateFrame(&frames.WindowUpdateFrame{
StreamID: 5,
ByteOffset: 0x8000,
ByteOffset: 100,
})
Expect(err).ToNot(HaveOccurred())
Expect(session.flowControlManager.SendWindowSize(5)).To(Equal(protocol.ByteCount(0x8000)))
Expect(session.flowControlManager.SendWindowSize(5)).To(Equal(protocol.ByteCount(100)))
})
It("updates the Flow Control Window of the connection", func() {

View File

@@ -94,8 +94,8 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
maxLen := maxBytes - currentLen - frameHeaderBytes
if s.lenOfDataForWriting() != 0 {
fcAllowance, _ := f.getFCAllowanceForStream(s) // can never error
maxLen = utils.MinByteCount(maxLen, fcAllowance)
sendWindowSize, _ := f.flowControlManager.SendWindowSize(s.streamID)
maxLen = utils.MinByteCount(maxLen, sendWindowSize)
}
if maxLen == 0 {
@@ -118,14 +118,12 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
f.flowControlManager.AddBytesSent(s.streamID, protocol.ByteCount(len(data)))
// Finally, check if we are now FC blocked and should queue a BLOCKED frame
individualFcOffset, _ := f.flowControlManager.SendWindowSize(s.streamID) // can never error
if s.writeOffset == individualFcOffset {
// We are now stream-level FC blocked
f.blockedFrameQueue = append(f.blockedFrameQueue, &frames.BlockedFrame{StreamID: s.StreamID()})
}
if f.flowControlManager.RemainingConnectionWindowSize() == 0 {
// We are now connection-level FC blocked
f.blockedFrameQueue = append(f.blockedFrameQueue, &frames.BlockedFrame{StreamID: 0})
} else if individualWindowSize, _ := f.flowControlManager.SendWindowSize(s.streamID); individualWindowSize == 0 {
// We are now stream-level FC blocked
f.blockedFrameQueue = append(f.blockedFrameQueue, &frames.BlockedFrame{StreamID: s.StreamID()})
}
res = append(res, frame)
@@ -135,27 +133,6 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
return
}
func (f *streamFramer) getFCAllowanceForStream(s *stream) (protocol.ByteCount, error) {
flowControlWindow, err := f.flowControlManager.SendWindowSize(s.streamID)
if err != nil {
return 0, err
}
flowControlWindow -= s.writeOffset
if flowControlWindow == 0 {
return 0, nil
}
contributes, err := f.flowControlManager.StreamContributesToConnectionFlowControl(s.StreamID())
if err != nil {
return 0, err
}
connectionWindow := protocol.ByteCount(protocol.MaxByteCount)
if contributes {
connectionWindow = f.flowControlManager.RemainingConnectionWindowSize()
}
return utils.MinByteCount(flowControlWindow, connectionWindow), nil
}
// maybeSplitOffFrame removes the first n bytes and returns them as a separate frame. If n >= len(frame), nil is returned and nothing is modified.
func maybeSplitOffFrame(frame *frames.StreamFrame, n protocol.ByteCount) *frames.StreamFrame {
if n >= frame.DataLen() {

View File

@@ -226,7 +226,7 @@ var _ = Describe("Stream Framer", func() {
It("returns a smaller frame if the whole frame doesn't fit in the stream flow control window, for non-zero StreamFrame offset", func() {
stream1.writeOffset = 1
stream1.dataForWriting = []byte("foobar")
fcm.sendWindowSizes[stream1.StreamID()] = 4
fcm.sendWindowSizes[stream1.StreamID()] = 3
fs := framer.PopStreamFrames(1000)
Expect(fs).To(HaveLen(1))
Expect(fs[0].Data).To(Equal([]byte("foo")))

View File

@@ -9,6 +9,7 @@ import (
"github.com/lucas-clemente/quic-go/frames"
"github.com/lucas-clemente/quic-go/handshake"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -61,6 +62,7 @@ func (m *mockFlowControlHandler) UpdateHighestReceived(streamID protocol.StreamI
func (m *mockFlowControlHandler) AddBytesSent(streamID protocol.StreamID, n protocol.ByteCount) error {
m.bytesSent += n
m.sendWindowSizes[streamID] -= n
for _, s := range m.streamsContributing {
if s == streamID {
m.remainingConnectionWindowSize -= n
@@ -71,11 +73,19 @@ func (m *mockFlowControlHandler) AddBytesSent(streamID protocol.StreamID, n prot
}
func (m *mockFlowControlHandler) SendWindowSize(streamID protocol.StreamID) (protocol.ByteCount, error) {
return m.sendWindowSizes[streamID], nil
res := m.sendWindowSizes[streamID]
for _, s := range m.streamsContributing {
if s == streamID {
return utils.MinByteCount(res, m.remainingConnectionWindowSize), nil
}
}
return res, nil
}
func (m *mockFlowControlHandler) RemainingConnectionWindowSize() protocol.ByteCount {
return m.remainingConnectionWindowSize
}
func (m *mockFlowControlHandler) UpdateWindow(streamID protocol.StreamID, offset protocol.ByteCount) (bool, error) {
panic("not implemented")
}