Files
quic-go/frames/ack_frame_new.go

323 lines
8.3 KiB
Go

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
}
// ParseAckFrameNew reads an ACK frame
func ParseAckFrameNew(r *bytes.Reader, version protocol.VersionNumber) (*AckFrameNew, error) {
frame := &AckFrameNew{}
typeByte, err := r.ReadByte()
if err != nil {
return nil, err
}
hasMissingRanges := false
if typeByte&0x20 == 0x20 {
hasMissingRanges = true
}
largestObservedLen := 2 * ((typeByte & 0x0C) >> 2)
if largestObservedLen == 0 {
largestObservedLen = 1
}
missingSequenceNumberDeltaLen := 2 * (typeByte & 0x03)
if missingSequenceNumberDeltaLen == 0 {
missingSequenceNumberDeltaLen = 1
}
largestObserved, err := utils.ReadUintN(r, largestObservedLen)
if err != nil {
return nil, err
}
frame.LargestObserved = protocol.PacketNumber(largestObserved)
delay, err := utils.ReadUfloat16(r)
if err != nil {
return nil, err
}
frame.DelayTime = time.Duration(delay) * time.Microsecond
var numAckBlocks uint8
if hasMissingRanges {
numAckBlocks, err = r.ReadByte()
if err != nil {
return nil, err
}
}
ackBlockLength, err := utils.ReadUintN(r, missingSequenceNumberDeltaLen)
if err != nil {
return nil, err
}
if ackBlockLength > largestObserved {
return nil, errInvalidAckRanges
}
if hasMissingRanges {
ackRange := AckRange{
FirstPacketNumber: protocol.PacketNumber(largestObserved-ackBlockLength) + 1,
LastPacketNumber: frame.LargestObserved,
}
frame.AckRanges = append(frame.AckRanges, ackRange)
var inLongBlock bool
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
}
length := protocol.PacketNumber(ackBlockLength)
if inLongBlock {
frame.AckRanges[len(frame.AckRanges)-1].FirstPacketNumber -= protocol.PacketNumber(gap) + length
frame.AckRanges[len(frame.AckRanges)-1].LastPacketNumber -= protocol.PacketNumber(gap)
} else {
ackRange := AckRange{
LastPacketNumber: frame.AckRanges[len(frame.AckRanges)-1].FirstPacketNumber - protocol.PacketNumber(gap) - 1,
}
ackRange.FirstPacketNumber = ackRange.LastPacketNumber - length + 1
frame.AckRanges = append(frame.AckRanges, ackRange)
}
inLongBlock = (ackBlockLength == 0)
}
frame.LowestAcked = frame.AckRanges[len(frame.AckRanges)-1].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()
if err != nil {
return nil, err
}
numTimestamp := uint8(numTimestampByte)
// Delta Largest observed
_, err = r.ReadByte()
if err != nil {
return nil, err
}
// First Timestamp
_, err = utils.ReadUint32(r)
if err != nil {
return nil, err
}
for i := 0; i < int(numTimestamp)-1; i++ {
// Delta Largest observed
_, err = r.ReadByte()
if err != nil {
return nil, err
}
// Time Since Previous Timestamp
_, err = utils.ReadUint16(r)
if err != nil {
return nil, err
}
}
return frame, nil
}
// Write writes an ACK frame.
func (f *AckFrameNew) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
largestObservedLen := protocol.GetPacketNumberLength(f.LargestObserved)
typeByte := uint8(0x40)
if largestObservedLen != protocol.PacketNumberLen1 {
typeByte ^= (uint8(largestObservedLen / 2)) << 2
}
// TODO: send shorter values, if possible
missingSequenceNumberDeltaLen := protocol.PacketNumberLen6
if missingSequenceNumberDeltaLen != protocol.PacketNumberLen1 {
typeByte ^= (uint8(missingSequenceNumberDeltaLen / 2))
}
if f.HasMissingRanges() {
typeByte |= (0x20 | 0x03)
}
b.WriteByte(typeByte)
switch largestObservedLen {
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))
}
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 = f.numWrittenNackRanges()
if numRanges >= 0xFF {
panic("AckFrame: Too many ACK ranges")
}
b.WriteByte(uint8(numRanges - 1))
}
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))
numRangesWritten++
}
for i, ackRange := range f.AckRanges {
if i == 0 {
continue
}
length := ackRange.LastPacketNumber - ackRange.FirstPacketNumber + 1
gap := f.AckRanges[i-1].FirstPacketNumber - ackRange.LastPacketNumber - 1
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
b.WriteByte(0x00) // Delta Largest observed
utils.WriteUint32(b, 0) // First timestamp
return nil
}
// MinLength of a written frame
func (f *AckFrameNew) MinLength(version protocol.VersionNumber) (protocol.ByteCount, error) {
var length protocol.ByteCount
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))
missingSequenceNumberDeltaLen := protocol.ByteCount(protocol.PacketNumberLen6)
if f.HasMissingRanges() {
length += (1 + missingSequenceNumberDeltaLen) * protocol.ByteCount(f.numWrittenNackRanges())
} else {
length += missingSequenceNumberDeltaLen
}
length += (1 + 2) * 0 /* TODO: num_timestamps */
return length, nil
}
// HasMissingRanges returns if this frame reports any missing packets
func (f *AckFrameNew) HasMissingRanges() bool {
if len(f.AckRanges) > 0 {
return true
}
return false
}
// GetHighestInOrderPacketNumber gets the highest in order packet number that is confirmed by this ACK
func (f *AckFrameNew) GetHighestInOrderPacketNumber() protocol.PacketNumber {
if f.HasMissingRanges() {
panic("NACKs not yet implemented")
}
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
}