implement basic writing of ACK blocks for QUIC 34 ACK frames

ref #182
This commit is contained in:
Marten Seemann
2016-06-21 00:24:44 +07:00
parent c681fd1469
commit cc5fe06db9
2 changed files with 120 additions and 37 deletions

View File

@@ -167,12 +167,15 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
typeByte ^= (uint8(largestObservedLen / 2)) << 2
}
missingSequenceNumberDeltaLen := largestObservedLen
// TODO: send shorter values, if possible
missingSequenceNumberDeltaLen := protocol.PacketNumberLen6
if missingSequenceNumberDeltaLen != protocol.PacketNumberLen1 {
typeByte ^= (uint8(missingSequenceNumberDeltaLen / 2))
}
f.DelayTime = time.Now().Sub(f.PacketReceivedTime)
if f.HasMissingRanges() {
typeByte |= (0x20 | 0x03)
}
b.WriteByte(typeByte)
@@ -187,22 +190,39 @@ func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) err
utils.WriteUint48(b, uint64(f.LargestObserved))
}
f.DelayTime = time.Now().Sub(f.PacketReceivedTime)
utils.WriteUfloat16(b, uint64(f.DelayTime/time.Microsecond))
// TODO: write number of ACK blocks, if present
switch missingSequenceNumberDeltaLen {
case protocol.PacketNumberLen1:
b.WriteByte(uint8(f.LargestObserved))
case protocol.PacketNumberLen2:
utils.WriteUint16(b, uint16(f.LargestObserved))
case protocol.PacketNumberLen4:
utils.WriteUint32(b, uint32(f.LargestObserved))
case protocol.PacketNumberLen6:
utils.WriteUint48(b, uint64(f.LargestObserved))
if f.HasMissingRanges() {
numRanges := len(f.AckRanges)
if numRanges >= 0xFF {
panic("AckFrame: Too many ACK ranges")
}
b.WriteByte(uint8(numRanges - 1))
}
// TODO: write ACK blocks
if !f.HasMissingRanges() {
utils.WriteUint48(b, uint64(f.LargestObserved-f.LowestAcked))
} else {
if f.LargestObserved != f.AckRanges[0].LastPacketNumber {
return errors.New("internal inconsistency")
}
length := f.LargestObserved - f.AckRanges[0].FirstPacketNumber + 1
utils.WriteUint48(b, uint64(length))
}
for i, ackRange := range f.AckRanges {
if i == 0 {
continue
}
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))
}
b.WriteByte(0x01) // Just one timestamp
b.WriteByte(0x00) // Delta Largest observed
@@ -217,7 +237,7 @@ func (f *AckFrameNew) MinLength(version protocol.VersionNumber) (protocol.ByteCo
length = 1 + 2 + 1 + 1 + 4 // 1 TypeByte, 2 ACK delay time, 1 Num Timestamp, 1 Delta Largest Observed, 4 FirstTimestamp
length += protocol.ByteCount(protocol.GetPacketNumberLength(f.LargestObserved))
// for the first ACK block length
length += protocol.ByteCount(protocol.GetPacketNumberLength(f.LargestObserved))
length += protocol.ByteCount(protocol.PacketNumberLen6)
length += (1 + 2) * 0 /* TODO: num_timestamps */
if f.HasMissingRanges() {

View File

@@ -155,10 +155,95 @@ var _ = Describe("AckFrame", func() {
Context("when writing", func() {
var b *bytes.Buffer
BeforeEach(func() {
b = &bytes.Buffer{}
})
Context("self-consistency", func() {
It("writes a simple ACK frame", func() {
frameOrig := &AckFrameNew{
LargestObserved: 1,
}
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.HasMissingRanges()).To(BeFalse())
Expect(r.Len()).To(BeZero())
})
It("writes the correct block length in a simple ACK frame", func() {
frameOrig := &AckFrameNew{
LargestObserved: 20,
LowestAcked: 10,
}
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.LowestAcked).To(Equal(frameOrig.LowestAcked))
Expect(frame.HasMissingRanges()).To(BeFalse())
Expect(r.Len()).To(BeZero())
})
It("writes a simple ACK frame with a high packet number", func() {
frameOrig := &AckFrameNew{
LargestObserved: 0xDEADBEEFCAFE,
}
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.HasMissingRanges()).To(BeFalse())
Expect(r.Len()).To(BeZero())
})
It("writes an ACK frame with one packet missing", func() {
frameOrig := &AckFrameNew{
LargestObserved: 40,
AckRanges: []AckRange{
AckRange{FirstPacketNumber: 25, LastPacketNumber: 40},
AckRange{FirstPacketNumber: 1, LastPacketNumber: 23},
},
}
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))
Expect(r.Len()).To(BeZero())
})
It("writes an ACK frame with multiple missing packets", func() {
frameOrig := &AckFrameNew{
LargestObserved: 25,
AckRanges: []AckRange{
AckRange{FirstPacketNumber: 22, LastPacketNumber: 25},
AckRange{FirstPacketNumber: 15, LastPacketNumber: 18},
AckRange{FirstPacketNumber: 13, LastPacketNumber: 13},
AckRange{FirstPacketNumber: 1, LastPacketNumber: 10},
},
}
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))
Expect(r.Len()).To(BeZero())
})
})
Context("min length", func() {
It("has proper min length", func() {
f := &AckFrameNew{
@@ -185,27 +270,5 @@ var _ = Describe("AckFrame", func() {
}
Expect(frame.GetHighestInOrderPacketNumber()).To(Equal(protocol.PacketNumber(0x1337)))
})
})
Context("self-consistency checks", func() {
var b *bytes.Buffer
BeforeEach(func() {
b = &bytes.Buffer{}
})
It("is self-consistent for ACK frames without NACK ranges", func() {
frameOrig := &AckFrameNew{
LargestObserved: 1,
}
err := frameOrig.Write(b, protocol.Version34)
Expect(err).ToNot(HaveOccurred())
r := bytes.NewReader(b.Bytes())
frame, err := ParseAckFrameNew(r, protocol.Version34)
Expect(err).ToNot(HaveOccurred())
Expect(frame.LargestObserved).To(Equal(frameOrig.LargestObserved))
Expect(frame.HasMissingRanges()).To(BeFalse())
Expect(r.Len()).To(BeZero())
})
})
})