forked from quic-go/quic-go
send shorter Missing Packet Sequence Number Delta in new ACK frames
fixes #184
This commit is contained in:
@@ -195,14 +195,13 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
|
||||
typeByte ^= (uint8(largestAckedLen / 2)) << 2
|
||||
}
|
||||
|
||||
// TODO: send shorter values, if possible
|
||||
missingSequenceNumberDeltaLen := protocol.PacketNumberLen6
|
||||
missingSequenceNumberDeltaLen := f.getMissingSequenceNumberDeltaLen()
|
||||
if missingSequenceNumberDeltaLen != protocol.PacketNumberLen1 {
|
||||
typeByte ^= (uint8(missingSequenceNumberDeltaLen / 2))
|
||||
}
|
||||
|
||||
if f.HasMissingRanges() {
|
||||
typeByte |= (0x20 | 0x03)
|
||||
typeByte |= 0x20
|
||||
}
|
||||
|
||||
b.WriteByte(typeByte)
|
||||
@@ -231,8 +230,9 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
|
||||
b.WriteByte(uint8(numRanges - 1))
|
||||
}
|
||||
|
||||
var firstAckBlockLength protocol.PacketNumber
|
||||
if !f.HasMissingRanges() {
|
||||
utils.WriteUint48(b, uint64(f.LargestAcked-f.LowestAcked+1))
|
||||
firstAckBlockLength = f.LargestAcked - f.LowestAcked + 1
|
||||
} else {
|
||||
if f.LargestAcked != f.AckRanges[0].LastPacketNumber {
|
||||
return errInconsistentAckLargestAcked
|
||||
@@ -240,11 +240,21 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
|
||||
if f.LowestAcked != f.AckRanges[len(f.AckRanges)-1].FirstPacketNumber {
|
||||
return errInconsistentAckLowestAcked
|
||||
}
|
||||
length := f.LargestAcked - f.AckRanges[0].FirstPacketNumber + 1
|
||||
utils.WriteUint48(b, uint64(length))
|
||||
firstAckBlockLength = f.LargestAcked - f.AckRanges[0].FirstPacketNumber + 1
|
||||
numRangesWritten++
|
||||
}
|
||||
|
||||
switch missingSequenceNumberDeltaLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(firstAckBlockLength))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.WriteUint16(b, uint16(firstAckBlockLength))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.WriteUint32(b, uint32(firstAckBlockLength))
|
||||
case protocol.PacketNumberLen6:
|
||||
utils.WriteUint48(b, uint64(firstAckBlockLength))
|
||||
}
|
||||
|
||||
for i, ackRange := range f.AckRanges {
|
||||
if i == 0 {
|
||||
continue
|
||||
@@ -260,7 +270,16 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
|
||||
|
||||
if num == 1 {
|
||||
b.WriteByte(uint8(gap))
|
||||
utils.WriteUint48(b, uint64(length))
|
||||
switch missingSequenceNumberDeltaLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(length))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.WriteUint16(b, uint16(length))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.WriteUint32(b, uint32(length))
|
||||
case protocol.PacketNumberLen6:
|
||||
utils.WriteUint48(b, uint64(length))
|
||||
}
|
||||
numRangesWritten++
|
||||
} else {
|
||||
for i := 0; i < int(num); i++ {
|
||||
@@ -276,7 +295,17 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
|
||||
}
|
||||
|
||||
b.WriteByte(uint8(gapWritten))
|
||||
utils.WriteUint48(b, lengthWritten)
|
||||
switch missingSequenceNumberDeltaLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(lengthWritten))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.WriteUint16(b, uint16(lengthWritten))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.WriteUint32(b, uint32(lengthWritten))
|
||||
case protocol.PacketNumberLen6:
|
||||
utils.WriteUint48(b, uint64(lengthWritten))
|
||||
}
|
||||
|
||||
numRangesWritten++
|
||||
}
|
||||
}
|
||||
@@ -302,7 +331,7 @@ func (f *AckFrameNew) MinLength(version protocol.VersionNumber) (protocol.ByteCo
|
||||
length = 1 + 2 + 1 // 1 TypeByte, 2 ACK delay time, 1 Num Timestamp
|
||||
length += protocol.ByteCount(protocol.GetPacketNumberLength(f.LargestAcked))
|
||||
|
||||
missingSequenceNumberDeltaLen := protocol.ByteCount(protocol.PacketNumberLen6)
|
||||
missingSequenceNumberDeltaLen := protocol.ByteCount(f.getMissingSequenceNumberDeltaLen())
|
||||
|
||||
if f.HasMissingRanges() {
|
||||
length += (1 + missingSequenceNumberDeltaLen) * protocol.ByteCount(f.numWritableNackRanges())
|
||||
@@ -390,3 +419,30 @@ func (f *AckFrameNew) numWritableNackRanges() uint64 {
|
||||
|
||||
return numRanges + 1
|
||||
}
|
||||
|
||||
func (f *AckFrameNew) getMissingSequenceNumberDeltaLen() protocol.PacketNumberLen {
|
||||
var maxRangeLength protocol.PacketNumber
|
||||
|
||||
if f.HasMissingRanges() {
|
||||
for _, ackRange := range f.AckRanges {
|
||||
rangeLength := ackRange.LastPacketNumber - ackRange.FirstPacketNumber + 1
|
||||
if rangeLength > maxRangeLength {
|
||||
maxRangeLength = rangeLength
|
||||
}
|
||||
}
|
||||
} else {
|
||||
maxRangeLength = f.LargestAcked - f.LowestAcked + 1
|
||||
}
|
||||
|
||||
if maxRangeLength <= 0xFF {
|
||||
return protocol.PacketNumberLen1
|
||||
}
|
||||
if maxRangeLength <= 0xFFFF {
|
||||
return protocol.PacketNumberLen2
|
||||
}
|
||||
if maxRangeLength <= 0xFFFFFFFF {
|
||||
return protocol.PacketNumberLen4
|
||||
}
|
||||
|
||||
return protocol.PacketNumberLen6
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ var _ = Describe("AckFrame", func() {
|
||||
Expect(err).To(MatchError(errInconsistentAckLowestAcked))
|
||||
})
|
||||
|
||||
Context("longer ACK blocks", func() {
|
||||
Context("longer gaps between ACK blocks", func() {
|
||||
It("only writes one block for 254 lost packets", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestAcked: 300,
|
||||
@@ -475,6 +475,115 @@ var _ = Describe("AckFrame", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Context("longer ACK blocks", func() {
|
||||
It("writes a 1 byte Missing Sequence Number Delta", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestAcked: 200,
|
||||
LowestAcked: 1,
|
||||
}
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x0)))
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked))
|
||||
Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked))
|
||||
Expect(r.Len()).To(BeZero())
|
||||
})
|
||||
|
||||
It("writes a 2 byte Missing Sequence Number Delta", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestAcked: 0x100,
|
||||
LowestAcked: 1,
|
||||
}
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x1)))
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked))
|
||||
Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked))
|
||||
Expect(r.Len()).To(BeZero())
|
||||
})
|
||||
|
||||
It("writes a 4 byte Missing Sequence Number Delta", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestAcked: 0x10000,
|
||||
LowestAcked: 1,
|
||||
}
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x2)))
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked))
|
||||
Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked))
|
||||
Expect(r.Len()).To(BeZero())
|
||||
})
|
||||
|
||||
It("writes a 6 byte Missing Sequence Number Delta", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestAcked: 0x100000000,
|
||||
LowestAcked: 1,
|
||||
}
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x3)))
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked))
|
||||
Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked))
|
||||
Expect(r.Len()).To(BeZero())
|
||||
})
|
||||
|
||||
It("writes a 1 byte Missing Sequence Number Delta, if all ACK blocks are short", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestAcked: 5001,
|
||||
LowestAcked: 1,
|
||||
AckRanges: []AckRange{
|
||||
AckRange{FirstPacketNumber: 5000, LastPacketNumber: 5001},
|
||||
AckRange{FirstPacketNumber: 250, LastPacketNumber: 300},
|
||||
AckRange{FirstPacketNumber: 1, LastPacketNumber: 200},
|
||||
},
|
||||
}
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x0)))
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked))
|
||||
Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked))
|
||||
Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges))
|
||||
Expect(r.Len()).To(BeZero())
|
||||
})
|
||||
|
||||
It("writes a 2 byte Missing Sequence Number Delta, for a frame with 2 ACK ranges", func() {
|
||||
frameOrig := &AckFrameNew{
|
||||
LargestAcked: 10000,
|
||||
LowestAcked: 1,
|
||||
AckRanges: []AckRange{
|
||||
AckRange{FirstPacketNumber: 9990, LastPacketNumber: 10000},
|
||||
AckRange{FirstPacketNumber: 1, LastPacketNumber: 256},
|
||||
},
|
||||
}
|
||||
err := frameOrig.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x1)))
|
||||
r := bytes.NewReader(b.Bytes())
|
||||
frame, err := ParseAckFrameNew(r, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked))
|
||||
Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked))
|
||||
Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges))
|
||||
Expect(r.Len()).To(BeZero())
|
||||
})
|
||||
})
|
||||
|
||||
Context("too many ACK blocks", func() {
|
||||
It("skips the lowest ACK ranges, if there are more than 255 AckRanges", func() {
|
||||
ackRanges := make([]AckRange, 300)
|
||||
@@ -590,6 +699,22 @@ var _ = Describe("AckFrame", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(f.MinLength(0)).To(Equal(protocol.ByteCount(b.Len())))
|
||||
})
|
||||
|
||||
It("has the proper min length for an ACK with a long ACK range", func() {
|
||||
largestAcked := protocol.PacketNumber(2 + 0xFFFFFF)
|
||||
f := &AckFrameNew{
|
||||
LargestAcked: largestAcked,
|
||||
LowestAcked: 1,
|
||||
AckRanges: []AckRange{
|
||||
AckRange{FirstPacketNumber: 1500, LastPacketNumber: largestAcked},
|
||||
AckRange{FirstPacketNumber: 290, LastPacketNumber: 295},
|
||||
AckRange{FirstPacketNumber: 1, LastPacketNumber: 19},
|
||||
},
|
||||
}
|
||||
err := f.Write(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(f.MinLength(0)).To(Equal(protocol.ByteCount(b.Len())))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user