forked from quic-go/quic-go
implement writing of ACK blocks with large gaps for QUIC 34 ACK frames
ref #182
This commit is contained in:
@@ -32,9 +32,9 @@ func ParseAckFrameNew(r *bytes.Reader, version protocol.VersionNumber) (*AckFram
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasNACK := false
|
||||
hasMissingRanges := false
|
||||
if typeByte&0x20 == 0x20 {
|
||||
hasNACK = true
|
||||
hasMissingRanges = true
|
||||
}
|
||||
|
||||
largestObservedLen := 2 * ((typeByte & 0x0C) >> 2)
|
||||
@@ -60,7 +60,7 @@ func ParseAckFrameNew(r *bytes.Reader, version protocol.VersionNumber) (*AckFram
|
||||
frame.DelayTime = time.Duration(delay) * time.Microsecond
|
||||
|
||||
var numAckBlocks uint8
|
||||
if hasNACK {
|
||||
if hasMissingRanges {
|
||||
numAckBlocks, err = r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -76,7 +76,7 @@ func ParseAckFrameNew(r *bytes.Reader, version protocol.VersionNumber) (*AckFram
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
|
||||
if hasNACK {
|
||||
if hasMissingRanges {
|
||||
ackRange := AckRange{
|
||||
FirstPacketNumber: protocol.PacketNumber(largestObserved-ackBlockLength) + 1,
|
||||
LastPacketNumber: frame.LargestObserved,
|
||||
@@ -193,8 +193,10 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
|
||||
f.DelayTime = time.Now().Sub(f.PacketReceivedTime)
|
||||
utils.WriteUfloat16(b, uint64(f.DelayTime/time.Microsecond))
|
||||
|
||||
var numRanges uint64
|
||||
var numRangesWritten uint64 // to check for internal consistency
|
||||
if f.HasMissingRanges() {
|
||||
numRanges := len(f.AckRanges)
|
||||
numRanges = f.numWrittenNackRanges()
|
||||
if numRanges >= 0xFF {
|
||||
panic("AckFrame: Too many ACK ranges")
|
||||
}
|
||||
@@ -209,6 +211,7 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
|
||||
}
|
||||
length := f.LargestObserved - f.AckRanges[0].FirstPacketNumber + 1
|
||||
utils.WriteUint48(b, uint64(length))
|
||||
numRangesWritten++
|
||||
}
|
||||
|
||||
for i, ackRange := range f.AckRanges {
|
||||
@@ -217,11 +220,39 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
|
||||
}
|
||||
|
||||
length := ackRange.LastPacketNumber - ackRange.FirstPacketNumber + 1
|
||||
// TODO: implement large gaps
|
||||
gap := f.AckRanges[i-1].FirstPacketNumber - ackRange.LastPacketNumber - 1
|
||||
|
||||
b.WriteByte(uint8(gap))
|
||||
utils.WriteUint48(b, uint64(length))
|
||||
num := gap/0xFF + 1
|
||||
if gap%0xFF == 0 {
|
||||
num--
|
||||
}
|
||||
|
||||
if num == 1 {
|
||||
b.WriteByte(uint8(gap))
|
||||
utils.WriteUint48(b, uint64(length))
|
||||
numRangesWritten++
|
||||
} else {
|
||||
for i := 0; i < int(num); i++ {
|
||||
var lengthWritten uint64
|
||||
var gapWritten uint8
|
||||
|
||||
if i == int(num)-1 { // last block
|
||||
lengthWritten = uint64(length)
|
||||
gapWritten = uint8(gap % 0xFF)
|
||||
} else {
|
||||
lengthWritten = 0
|
||||
gapWritten = 0xFF
|
||||
}
|
||||
|
||||
b.WriteByte(uint8(gapWritten))
|
||||
utils.WriteUint48(b, lengthWritten)
|
||||
numRangesWritten++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if numRanges != numRangesWritten {
|
||||
return errors.New("BUG: Inconsistent number of ACK ranges written")
|
||||
}
|
||||
|
||||
b.WriteByte(0x01) // Just one timestamp
|
||||
@@ -266,3 +297,27 @@ func (f *AckFrameNew) GetHighestInOrderPacketNumber() protocol.PacketNumber {
|
||||
}
|
||||
return f.LargestObserved
|
||||
}
|
||||
|
||||
// numWrittenNackRanges calculates the number of ACK blocks that are about to be written
|
||||
// this number is different from len(f.AckRanges) for the case of long gaps (> 255 packets)
|
||||
func (f *AckFrameNew) numWrittenNackRanges() uint64 {
|
||||
if len(f.AckRanges) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
var numRanges uint64
|
||||
for i, ackRange := range f.AckRanges {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
lastAckRange := f.AckRanges[i-1]
|
||||
gap := lastAckRange.FirstPacketNumber - ackRange.LastPacketNumber
|
||||
numRanges += 1 + uint64(gap)/0xFF
|
||||
if uint64(gap)%(0xFF+1) == 0 {
|
||||
numRanges--
|
||||
}
|
||||
}
|
||||
|
||||
return numRanges + 1
|
||||
}
|
||||
|
||||
@@ -242,6 +242,81 @@ var _ = Describe("AckFrame", func() {
|
||||
Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges))
|
||||
Expect(r.Len()).To(BeZero())
|
||||
})
|
||||
|
||||
Context("longer ACK blocks", func() {
|
||||
It("only writes one block for 255 lost packets", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestObserved: 300,
|
||||
AckRanges: []AckRange{
|
||||
AckRange{FirstPacketNumber: 275, LastPacketNumber: 300},
|
||||
AckRange{FirstPacketNumber: 1, LastPacketNumber: 19},
|
||||
},
|
||||
}
|
||||
Expect(frameOrig.numWrittenNackRanges()).To(Equal(uint64(2)))
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestObserved).To(Equal(frameOrig.LargestObserved))
|
||||
Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges))
|
||||
})
|
||||
|
||||
It("writes two blocks for 256 lost packets", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestObserved: 300,
|
||||
AckRanges: []AckRange{
|
||||
AckRange{FirstPacketNumber: 276, LastPacketNumber: 300},
|
||||
AckRange{FirstPacketNumber: 1, LastPacketNumber: 19},
|
||||
},
|
||||
}
|
||||
Expect(frameOrig.numWrittenNackRanges()).To(Equal(uint64(3)))
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Expect(b.Bytes()[13+0*(1+6) : 13+1*(1+6)]).To(Equal([]byte{0xFF, 0, 0, 0, 0, 0, 0}))
|
||||
// Expect(b.Bytes()[13+1*(1+6) : 13+2*(1+6)]).To(Equal([]byte{0x1, 0, 0, 0, 0, 0, 19}))
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestObserved).To(Equal(frameOrig.LargestObserved))
|
||||
Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges))
|
||||
})
|
||||
|
||||
It("writes multiple blocks for a lot of lost packets", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestObserved: 3000,
|
||||
AckRanges: []AckRange{
|
||||
AckRange{FirstPacketNumber: 2900, LastPacketNumber: 3000},
|
||||
AckRange{FirstPacketNumber: 1, LastPacketNumber: 19},
|
||||
},
|
||||
}
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestObserved).To(Equal(frameOrig.LargestObserved))
|
||||
Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges))
|
||||
})
|
||||
|
||||
It("writes multiple longer blocks for 256 lost packets", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestObserved: 3600,
|
||||
AckRanges: []AckRange{
|
||||
AckRange{FirstPacketNumber: 2900, LastPacketNumber: 3600},
|
||||
AckRange{FirstPacketNumber: 1000, LastPacketNumber: 2500},
|
||||
AckRange{FirstPacketNumber: 1, LastPacketNumber: 19},
|
||||
},
|
||||
}
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestObserved).To(Equal(frameOrig.LargestObserved))
|
||||
Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("min length", func() {
|
||||
|
||||
Reference in New Issue
Block a user