forked from quic-go/quic-go
@@ -2,17 +2,22 @@ package frames
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
var errInvalidAckRanges = errors.New("AckFrame: ACK frame contains invalid ACK ranges")
|
||||
|
||||
// An AckFrameNew is a ACK frame in QUIC c34
|
||||
type AckFrameNew struct {
|
||||
// TODO: rename to LargestAcked
|
||||
LargestObserved protocol.PacketNumber
|
||||
NackRanges []NackRange // has to be ordered. The NACK range with the highest FirstPacketNumber goes first, the NACK range with the lowest FirstPacketNumber goes last
|
||||
LowestAcked protocol.PacketNumber
|
||||
AckRanges []AckRange
|
||||
|
||||
DelayTime time.Duration
|
||||
PacketReceivedTime time.Time // only for received packets. Will not be modified for received ACKs frames
|
||||
@@ -32,10 +37,6 @@ func ParseAckFrameNew(r *bytes.Reader, version protocol.VersionNumber) (*AckFram
|
||||
hasNACK = true
|
||||
}
|
||||
|
||||
if hasNACK {
|
||||
panic("NACKs not yet implemented")
|
||||
}
|
||||
|
||||
largestObservedLen := 2 * ((typeByte & 0x0C) >> 2)
|
||||
if largestObservedLen == 0 {
|
||||
largestObservedLen = 1
|
||||
@@ -58,15 +59,58 @@ func ParseAckFrameNew(r *bytes.Reader, version protocol.VersionNumber) (*AckFram
|
||||
}
|
||||
frame.DelayTime = time.Duration(delay) * time.Microsecond
|
||||
|
||||
// TODO: read number of ACK blocks if n flag is set
|
||||
var numAckBlocks uint8
|
||||
if hasNACK {
|
||||
numAckBlocks, err = r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ackBlockLength, err := utils.ReadUintN(r, missingSequenceNumberDeltaLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
utils.Debugf("ackBlockLength: %d", ackBlockLength)
|
||||
|
||||
// TODO: read ACK blocks
|
||||
if ackBlockLength > largestObserved {
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
|
||||
if hasNACK {
|
||||
ackRange := AckRange{
|
||||
FirstPacketNumber: protocol.PacketNumber(largestObserved-ackBlockLength) + 1,
|
||||
LastPacketNumber: frame.LargestObserved,
|
||||
}
|
||||
frame.AckRanges = append(frame.AckRanges, ackRange)
|
||||
|
||||
for i := uint8(0); i < numAckBlocks; i++ {
|
||||
var gap uint8
|
||||
gap, err = r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ackBlockLength, err = utils.ReadUintN(r, missingSequenceNumberDeltaLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ackRange := AckRange{
|
||||
LastPacketNumber: frame.AckRanges[i].FirstPacketNumber - protocol.PacketNumber(gap) - 1,
|
||||
}
|
||||
ackRange.FirstPacketNumber = ackRange.LastPacketNumber - protocol.PacketNumber(ackBlockLength) + 1
|
||||
frame.AckRanges = append(frame.AckRanges, ackRange)
|
||||
}
|
||||
frame.LowestAcked = frame.AckRanges[numAckBlocks].FirstPacketNumber
|
||||
} else {
|
||||
// make sure that LowestAcked is not 0. 0 is not a valid PacketNumber
|
||||
// TODO: is this really the right behavior?
|
||||
if largestObserved == ackBlockLength {
|
||||
frame.LowestAcked = 1
|
||||
} else {
|
||||
frame.LowestAcked = protocol.PacketNumber(largestObserved - ackBlockLength)
|
||||
}
|
||||
}
|
||||
|
||||
var numTimestampByte byte
|
||||
numTimestampByte, err = r.ReadByte()
|
||||
|
||||
@@ -12,10 +12,11 @@ import (
|
||||
var _ = Describe("AckFrame", func() {
|
||||
Context("when parsing", func() {
|
||||
It("accepts a sample frame", func() {
|
||||
b := bytes.NewReader([]byte{0x40, 0x1a, 0x8e, 0x0, 0x1a, 0x1, 0x1, 0x6b, 0x26, 0x3, 0x0})
|
||||
frame, err := ParseAckFrameNew(b, protocol.Version34)
|
||||
b := bytes.NewReader([]byte{0x40, 0x1c, 0x8e, 0x0, 0x1c, 0x1, 0x1, 0x6b, 0x26, 0x3, 0x0})
|
||||
frame, err := ParseAckFrameNew(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestObserved).To(Equal(protocol.PacketNumber(0x1a)))
|
||||
Expect(frame.LargestObserved).To(Equal(protocol.PacketNumber(0x1c)))
|
||||
Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(1)))
|
||||
Expect(frame.DelayTime).To(Equal(142 * time.Microsecond))
|
||||
Expect(frame.HasNACK()).To(Equal(false))
|
||||
Expect(b.Len()).To(BeZero())
|
||||
@@ -23,7 +24,7 @@ var _ = Describe("AckFrame", func() {
|
||||
|
||||
It("parses a frame with a 48 bit packet number", func() {
|
||||
b := bytes.NewReader([]byte{0x4c, 0x37, 0x13, 0xad, 0xfb, 0xca, 0xde, 0x0, 0x0, 0x0, 0x1, 0, 0, 0, 0, 0})
|
||||
frame, err := ParseAckFrameNew(b, protocol.Version32)
|
||||
frame, err := ParseAckFrameNew(b, protocol.Version34)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestObserved).To(Equal(protocol.PacketNumber(0xdecafbad1337)))
|
||||
Expect(b.Len()).To(BeZero())
|
||||
@@ -31,10 +32,63 @@ var _ = Describe("AckFrame", func() {
|
||||
|
||||
It("parses a frame with multiple timestamps", func() {
|
||||
b := bytes.NewReader([]byte{0x40, 0x10, 0x0, 0x0, 0x10, 0x4, 0x1, 0x6b, 0x26, 0x4, 0x0, 0x3, 0, 0, 0x2, 0, 0, 0x1, 0, 0})
|
||||
_, err := ParseAckFrameNew(b, protocol.Version34)
|
||||
_, err := ParseAckFrameNew(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(b.Len()).To(BeZero())
|
||||
})
|
||||
|
||||
It("errors when the ACK range is too large", func() {
|
||||
// LargestObserved: 0x1c
|
||||
// Length: 0x1d => LowestAcked would be -1
|
||||
b := bytes.NewReader([]byte{0x40, 0x1c, 0x8e, 0x0, 0x1d, 0x1, 0x1, 0x6b, 0x26, 0x3, 0x0})
|
||||
_, err := ParseAckFrameNew(b, 0)
|
||||
Expect(err).To(MatchError(errInvalidAckRanges))
|
||||
})
|
||||
|
||||
Context("ACK blocks", func() {
|
||||
It("parses a frame with one ACK block", func() {
|
||||
b := bytes.NewReader([]byte{0x60, 0x18, 0x94, 0x1, 0x1, 0x3, 0x2, 0x13, 0x2, 0x1, 0x5c, 0xd5, 0x0, 0x0, 0x0, 0x95, 0x0})
|
||||
frame, err := ParseAckFrameNew(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestObserved).To(Equal(protocol.PacketNumber(24)))
|
||||
Expect(frame.AckRanges).To(HaveLen(2))
|
||||
Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 22, LastPacketNumber: 24}))
|
||||
Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: 1, LastPacketNumber: 19}))
|
||||
Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(1)))
|
||||
Expect(b.Len()).To(BeZero())
|
||||
})
|
||||
|
||||
It("parses a frame with multiple single packets missing", func() {
|
||||
b := bytes.NewReader([]byte{0x60, 0x27, 0xda, 0x0, 0x6, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x13, 0x2, 0x1, 0x71, 0x12, 0x3, 0x0, 0x0, 0x47, 0x2})
|
||||
frame, err := ParseAckFrameNew(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestObserved).To(Equal(protocol.PacketNumber(0x27)))
|
||||
Expect(frame.AckRanges).To(HaveLen(7))
|
||||
Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 31, LastPacketNumber: 0x27}))
|
||||
Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: 29, LastPacketNumber: 29}))
|
||||
Expect(frame.AckRanges[2]).To(Equal(AckRange{FirstPacketNumber: 27, LastPacketNumber: 27}))
|
||||
Expect(frame.AckRanges[3]).To(Equal(AckRange{FirstPacketNumber: 25, LastPacketNumber: 25}))
|
||||
Expect(frame.AckRanges[4]).To(Equal(AckRange{FirstPacketNumber: 23, LastPacketNumber: 23}))
|
||||
Expect(frame.AckRanges[5]).To(Equal(AckRange{FirstPacketNumber: 21, LastPacketNumber: 21}))
|
||||
Expect(frame.AckRanges[6]).To(Equal(AckRange{FirstPacketNumber: 1, LastPacketNumber: 19}))
|
||||
Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(1)))
|
||||
Expect(b.Len()).To(BeZero())
|
||||
})
|
||||
|
||||
It("parses a frame with multiple longer ACK blocks", func() {
|
||||
b := bytes.NewReader([]byte{0x60, 0x52, 0xd1, 0x0, 0x3, 0x17, 0xa, 0x10, 0x4, 0x8, 0x2, 0x13, 0x2, 0x1, 0x6c, 0xc8, 0x2, 0x0, 0x0, 0x7e, 0x1})
|
||||
frame, err := ParseAckFrameNew(b, 0)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(frame.LargestObserved).To(Equal(protocol.PacketNumber(0x52)))
|
||||
Expect(frame.AckRanges).To(HaveLen(4))
|
||||
Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 60, LastPacketNumber: 0x52}))
|
||||
Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: 34, LastPacketNumber: 49}))
|
||||
Expect(frame.AckRanges[2]).To(Equal(AckRange{FirstPacketNumber: 22, LastPacketNumber: 29}))
|
||||
Expect(frame.AckRanges[3]).To(Equal(AckRange{FirstPacketNumber: 1, LastPacketNumber: 19}))
|
||||
Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(1)))
|
||||
Expect(b.Len()).To(BeZero())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("when writing", func() {
|
||||
|
||||
9
frames/ack_range.go
Normal file
9
frames/ack_range.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package frames
|
||||
|
||||
import "github.com/lucas-clemente/quic-go/protocol"
|
||||
|
||||
// AckRange is an ACK range
|
||||
type AckRange struct {
|
||||
FirstPacketNumber protocol.PacketNumber
|
||||
LastPacketNumber protocol.PacketNumber
|
||||
}
|
||||
Reference in New Issue
Block a user