From 13f15c8c23367dfe8ea007bb2a81546ecfcdc49a Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Sun, 15 May 2016 09:52:31 +0700 Subject: [PATCH] add method to PacketPacker to send WindowUpdate frames work towards #19 --- packet_packer.go | 28 ++++++++++++++++++---- packet_packer_test.go | 55 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/packet_packer.go b/packet_packer.go index 3d0d9485..129f24a1 100644 --- a/packet_packer.go +++ b/packet_packer.go @@ -27,8 +27,9 @@ type packetPacker struct { sentPacketHandler ackhandler.SentPacketHandler connectionParametersManager *handshake.ConnectionParametersManager - streamFrameQueue StreamFrameQueue - controlFrames []frames.Frame + streamFrameQueue StreamFrameQueue + windowUpdateFrames []*frames.WindowUpdateFrame + controlFrames []frames.Frame lastPacketNumber protocol.PacketNumber } @@ -41,6 +42,10 @@ func (p *packetPacker) AddHighPrioStreamFrame(f frames.StreamFrame) { p.streamFrameQueue.Push(&f, true) } +func (p *packetPacker) AddWindowUpdateFrame(f *frames.WindowUpdateFrame) { + p.windowUpdateFrames = append(p.windowUpdateFrames, f) +} + func (p *packetPacker) PackPacket(stopWaitingFrame *frames.StopWaitingFrame, controlFrames []frames.Frame, includeStreamFrames bool) (*packedPacket, error) { // don't send out packets that only contain a StopWaitingFrame if len(controlFrames) == 0 && (p.streamFrameQueue.Len() == 0 || !includeStreamFrames) { @@ -122,9 +127,24 @@ func (p *packetPacker) getPayload(frames []frames.Frame, currentPacketNumber pro } func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFrame, publicHeaderLength protocol.ByteCount, includeStreamFrames bool) ([]frames.Frame, error) { - payloadLength := protocol.ByteCount(0) + var payloadLength protocol.ByteCount var payloadFrames []frames.Frame + maxFrameSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength + + // TODO: handle the extremely unlikely case that there are more windowUpdateFrames than we can fit into one packet + for len(p.windowUpdateFrames) > 0 { + frame := p.windowUpdateFrames[0] + minLength, _ := frame.MinLength() // windowUpdateFrames.MinLength() *never* returns an error + payloadLength += minLength + payloadFrames = append(payloadFrames, frame) + p.windowUpdateFrames = p.windowUpdateFrames[1:] + + if payloadLength > maxFrameSize { + panic("internal inconsistency: packet payload too large") + } + } + if stopWaitingFrame != nil { payloadFrames = append(payloadFrames, stopWaitingFrame) minLength, err := stopWaitingFrame.MinLength() @@ -134,8 +154,6 @@ func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFra payloadLength += minLength } - maxFrameSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength - for len(p.controlFrames) > 0 { frame := p.controlFrames[0] minLength, _ := frame.MinLength() // controlFrames does not contain any StopWaitingFrames. So it will *never* return an error diff --git a/packet_packer_test.go b/packet_packer_test.go index dc1a341e..f12e3c2d 100644 --- a/packet_packer_test.go +++ b/packet_packer_test.go @@ -147,15 +147,14 @@ var _ = Describe("Packet packer", func() { }) It("packs a lot of control frames into 2 packets if they don't fit into one", func() { - windowUpdateFrame := &frames.WindowUpdateFrame{ - StreamID: 0x1337, - ByteOffset: 0xDECAFBAD, + blockedFrame := &frames.BlockedFrame{ + StreamID: 0x1337, } - minLength, _ := windowUpdateFrame.MinLength() + minLength, _ := blockedFrame.MinLength() maxFramesPerPacket := int(protocol.MaxFrameAndPublicHeaderSize-publicHeaderLen) / int(minLength) var controlFrames []frames.Frame for i := 0; i < maxFramesPerPacket+10; i++ { - controlFrames = append(controlFrames, windowUpdateFrame) + controlFrames = append(controlFrames, blockedFrame) } packer.controlFrames = controlFrames payloadFrames, err := packer.composeNextPacket(nil, publicHeaderLen, true) @@ -187,6 +186,52 @@ var _ = Describe("Packet packer", func() { Expect(packer.lastPacketNumber).To(Equal(protocol.PacketNumber(2))) }) + Context("WindowUpdate Frame handling", func() { + It("packs one WindowUpdateFrame", func() { + f := &frames.WindowUpdateFrame{ + StreamID: 0x1337, + ByteOffset: 0xDECAFBAD, + } + packer.AddWindowUpdateFrame(f) + payloadFrames, err := packer.composeNextPacket(nil, publicHeaderLen, true) + Expect(err).ToNot(HaveOccurred()) + Expect(payloadFrames).To(HaveLen(1)) + Expect(payloadFrames[0]).To(Equal(f)) + }) + + It("packs multiple WindowUpdateFrame", func() { + f1 := &frames.WindowUpdateFrame{ + StreamID: 0x1337, + ByteOffset: 0xDECAFBAD, + } + f2 := &frames.WindowUpdateFrame{ + StreamID: 0x7331, + ByteOffset: 0xDABFACED, + } + packer.AddWindowUpdateFrame(f1) + packer.AddWindowUpdateFrame(f2) + payloadFrames, err := packer.composeNextPacket(nil, publicHeaderLen, true) + Expect(err).ToNot(HaveOccurred()) + Expect(payloadFrames).To(HaveLen(2)) + Expect(payloadFrames).To(ContainElement(f1)) + Expect(payloadFrames).To(ContainElement(f2)) + }) + + It("only packs a WindowUpdateFrame once", func() { + f := &frames.WindowUpdateFrame{ + StreamID: 0x1337, + ByteOffset: 0xDECAFBAD, + } + packer.AddWindowUpdateFrame(f) + payloadFrames, err := packer.composeNextPacket(nil, publicHeaderLen, true) + Expect(err).ToNot(HaveOccurred()) + Expect(payloadFrames).ToNot(BeNil()) + payloadFrames, err = packer.composeNextPacket(nil, publicHeaderLen, true) + Expect(err).ToNot(HaveOccurred()) + Expect(payloadFrames).To(BeNil()) + }) + }) + Context("Stream Frame handling", func() { It("does not splits a stream frame with maximum size", func() { f := frames.StreamFrame{