forked from quic-go/quic-go
This function was needed when we supported both Q039 (using big endian encoding) and ealier versions (using little endian encoding).
81 lines
2.5 KiB
Go
81 lines
2.5 KiB
Go
package wire
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
|
|
"github.com/lucas-clemente/quic-go/internal/protocol"
|
|
"github.com/lucas-clemente/quic-go/internal/utils"
|
|
)
|
|
|
|
// A StopWaitingFrame in QUIC
|
|
type StopWaitingFrame struct {
|
|
LeastUnacked protocol.PacketNumber
|
|
PacketNumberLen protocol.PacketNumberLen
|
|
// PacketNumber is the packet number of the packet that this StopWaitingFrame will be sent with
|
|
PacketNumber protocol.PacketNumber
|
|
}
|
|
|
|
var (
|
|
errLeastUnackedHigherThanPacketNumber = errors.New("StopWaitingFrame: LeastUnacked can't be greater than the packet number")
|
|
errPacketNumberNotSet = errors.New("StopWaitingFrame: PacketNumber not set")
|
|
errPacketNumberLenNotSet = errors.New("StopWaitingFrame: PacketNumberLen not set")
|
|
)
|
|
|
|
func (f *StopWaitingFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
|
// make sure the PacketNumber was set
|
|
if f.PacketNumber == protocol.PacketNumber(0) {
|
|
return errPacketNumberNotSet
|
|
}
|
|
if f.LeastUnacked > f.PacketNumber {
|
|
return errLeastUnackedHigherThanPacketNumber
|
|
}
|
|
|
|
b.WriteByte(0x06)
|
|
leastUnackedDelta := uint64(f.PacketNumber - f.LeastUnacked)
|
|
switch f.PacketNumberLen {
|
|
case protocol.PacketNumberLen1:
|
|
b.WriteByte(uint8(leastUnackedDelta))
|
|
case protocol.PacketNumberLen2:
|
|
utils.BigEndian.WriteUint16(b, uint16(leastUnackedDelta))
|
|
case protocol.PacketNumberLen4:
|
|
utils.BigEndian.WriteUint32(b, uint32(leastUnackedDelta))
|
|
case protocol.PacketNumberLen6:
|
|
utils.BigEndian.WriteUint48(b, leastUnackedDelta&(1<<48-1))
|
|
default:
|
|
return errPacketNumberLenNotSet
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MinLength of a written frame
|
|
func (f *StopWaitingFrame) MinLength(_ protocol.VersionNumber) (protocol.ByteCount, error) {
|
|
minLength := protocol.ByteCount(1) // typeByte
|
|
|
|
if f.PacketNumberLen == protocol.PacketNumberLenInvalid {
|
|
return 0, errPacketNumberLenNotSet
|
|
}
|
|
minLength += protocol.ByteCount(f.PacketNumberLen)
|
|
return minLength, nil
|
|
}
|
|
|
|
// ParseStopWaitingFrame parses a StopWaiting frame
|
|
func ParseStopWaitingFrame(r *bytes.Reader, packetNumber protocol.PacketNumber, packetNumberLen protocol.PacketNumberLen, _ protocol.VersionNumber) (*StopWaitingFrame, error) {
|
|
frame := &StopWaitingFrame{}
|
|
|
|
// read the TypeByte
|
|
if _, err := r.ReadByte(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
leastUnackedDelta, err := utils.BigEndian.ReadUintN(r, uint8(packetNumberLen))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if leastUnackedDelta > uint64(packetNumber) {
|
|
return nil, errors.New("invalid LeastUnackedDelta")
|
|
}
|
|
frame.LeastUnacked = protocol.PacketNumber(uint64(packetNumber) - leastUnackedDelta)
|
|
return frame, nil
|
|
}
|