239
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
generated
vendored
Normal file
239
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
generated
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// TODO: use the value sent in the transport parameters
|
||||
const ackDelayExponent = 3
|
||||
|
||||
// An AckFrame is an ACK frame
|
||||
type AckFrame struct {
|
||||
AckRanges []AckRange // has to be ordered. The highest ACK range goes first, the lowest ACK range goes last
|
||||
DelayTime time.Duration
|
||||
}
|
||||
|
||||
// parseAckFrame reads an ACK frame
|
||||
func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return parseAckFrameLegacy(r, version)
|
||||
}
|
||||
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ecn := typeByte&0x1 > 0
|
||||
|
||||
frame := &AckFrame{}
|
||||
|
||||
la, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
largestAcked := protocol.PacketNumber(la)
|
||||
delay, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.DelayTime = time.Duration(delay*1<<ackDelayExponent) * time.Microsecond
|
||||
|
||||
numBlocks, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// read the first ACK range
|
||||
ab, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ackBlock := protocol.PacketNumber(ab)
|
||||
if ackBlock > largestAcked {
|
||||
return nil, errors.New("invalid first ACK range")
|
||||
}
|
||||
smallest := largestAcked - ackBlock
|
||||
|
||||
// read all the other ACK ranges
|
||||
frame.AckRanges = append(frame.AckRanges, AckRange{Smallest: smallest, Largest: largestAcked})
|
||||
for i := uint64(0); i < numBlocks; i++ {
|
||||
g, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gap := protocol.PacketNumber(g)
|
||||
if smallest < gap+2 {
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
largest := smallest - gap - 2
|
||||
|
||||
ab, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ackBlock := protocol.PacketNumber(ab)
|
||||
|
||||
if ackBlock > largest {
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
smallest = largest - ackBlock
|
||||
frame.AckRanges = append(frame.AckRanges, AckRange{Smallest: smallest, Largest: largest})
|
||||
}
|
||||
|
||||
if !frame.validateAckRanges() {
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
|
||||
// parse (and skip) the ECN section
|
||||
if ecn {
|
||||
for i := 0; i < 3; i++ {
|
||||
if _, err := utils.ReadVarInt(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// Write writes an ACK frame.
|
||||
func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return f.writeLegacy(b, version)
|
||||
}
|
||||
|
||||
b.WriteByte(0x1a)
|
||||
utils.WriteVarInt(b, uint64(f.LargestAcked()))
|
||||
utils.WriteVarInt(b, encodeAckDelay(f.DelayTime))
|
||||
|
||||
numRanges := f.numEncodableAckRanges()
|
||||
utils.WriteVarInt(b, uint64(numRanges-1))
|
||||
|
||||
// write the first range
|
||||
_, firstRange := f.encodeAckRange(0)
|
||||
utils.WriteVarInt(b, firstRange)
|
||||
|
||||
// write all the other range
|
||||
for i := 1; i < numRanges; i++ {
|
||||
gap, len := f.encodeAckRange(i)
|
||||
utils.WriteVarInt(b, gap)
|
||||
utils.WriteVarInt(b, len)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *AckFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return f.lengthLegacy(version)
|
||||
}
|
||||
|
||||
largestAcked := f.AckRanges[0].Largest
|
||||
numRanges := f.numEncodableAckRanges()
|
||||
|
||||
length := 1 + utils.VarIntLen(uint64(largestAcked)) + utils.VarIntLen(encodeAckDelay(f.DelayTime))
|
||||
|
||||
length += utils.VarIntLen(uint64(numRanges - 1))
|
||||
lowestInFirstRange := f.AckRanges[0].Smallest
|
||||
length += utils.VarIntLen(uint64(largestAcked - lowestInFirstRange))
|
||||
|
||||
for i := 1; i < numRanges; i++ {
|
||||
gap, len := f.encodeAckRange(i)
|
||||
length += utils.VarIntLen(gap)
|
||||
length += utils.VarIntLen(len)
|
||||
}
|
||||
return length
|
||||
}
|
||||
|
||||
// gets the number of ACK ranges that can be encoded
|
||||
// such that the resulting frame is smaller than the maximum ACK frame size
|
||||
func (f *AckFrame) numEncodableAckRanges() int {
|
||||
length := 1 + utils.VarIntLen(uint64(f.LargestAcked())) + utils.VarIntLen(encodeAckDelay(f.DelayTime))
|
||||
length += 2 // assume that the number of ranges will consume 2 bytes
|
||||
for i := 1; i < len(f.AckRanges); i++ {
|
||||
gap, len := f.encodeAckRange(i)
|
||||
rangeLen := utils.VarIntLen(gap) + utils.VarIntLen(len)
|
||||
if length+rangeLen > protocol.MaxAckFrameSize {
|
||||
// Writing range i would exceed the MaxAckFrameSize.
|
||||
// So encode one range less than that.
|
||||
return i - 1
|
||||
}
|
||||
length += rangeLen
|
||||
}
|
||||
return len(f.AckRanges)
|
||||
}
|
||||
|
||||
func (f *AckFrame) encodeAckRange(i int) (uint64 /* gap */, uint64 /* length */) {
|
||||
if i == 0 {
|
||||
return 0, uint64(f.AckRanges[0].Largest - f.AckRanges[0].Smallest)
|
||||
}
|
||||
return uint64(f.AckRanges[i-1].Smallest - f.AckRanges[i].Largest - 2),
|
||||
uint64(f.AckRanges[i].Largest - f.AckRanges[i].Smallest)
|
||||
}
|
||||
|
||||
// HasMissingRanges returns if this frame reports any missing packets
|
||||
func (f *AckFrame) HasMissingRanges() bool {
|
||||
return len(f.AckRanges) > 1
|
||||
}
|
||||
|
||||
func (f *AckFrame) validateAckRanges() bool {
|
||||
if len(f.AckRanges) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// check the validity of every single ACK range
|
||||
for _, ackRange := range f.AckRanges {
|
||||
if ackRange.Smallest > ackRange.Largest {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// check the consistency for ACK with multiple NACK ranges
|
||||
for i, ackRange := range f.AckRanges {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
lastAckRange := f.AckRanges[i-1]
|
||||
if lastAckRange.Smallest <= ackRange.Smallest {
|
||||
return false
|
||||
}
|
||||
if lastAckRange.Smallest <= ackRange.Largest+1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// LargestAcked is the largest acked packet number
|
||||
func (f *AckFrame) LargestAcked() protocol.PacketNumber {
|
||||
return f.AckRanges[0].Largest
|
||||
}
|
||||
|
||||
// LowestAcked is the lowest acked packet number
|
||||
func (f *AckFrame) LowestAcked() protocol.PacketNumber {
|
||||
return f.AckRanges[len(f.AckRanges)-1].Smallest
|
||||
}
|
||||
|
||||
// AcksPacket determines if this ACK frame acks a certain packet number
|
||||
func (f *AckFrame) AcksPacket(p protocol.PacketNumber) bool {
|
||||
if p < f.LowestAcked() || p > f.LargestAcked() {
|
||||
return false
|
||||
}
|
||||
|
||||
i := sort.Search(len(f.AckRanges), func(i int) bool {
|
||||
return p >= f.AckRanges[i].Smallest
|
||||
})
|
||||
// i will always be < len(f.AckRanges), since we checked above that p is not bigger than the largest acked
|
||||
return p <= f.AckRanges[i].Largest
|
||||
}
|
||||
|
||||
func encodeAckDelay(delay time.Duration) uint64 {
|
||||
return uint64(delay.Nanoseconds() / (1000 * (1 << ackDelayExponent)))
|
||||
}
|
||||
364
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame_legacy.go
generated
vendored
Normal file
364
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame_legacy.go
generated
vendored
Normal file
@@ -0,0 +1,364 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
var errInvalidAckRanges = errors.New("AckFrame: ACK frame contains invalid ACK ranges")
|
||||
|
||||
func parseAckFrameLegacy(r *bytes.Reader, _ protocol.VersionNumber) (*AckFrame, error) {
|
||||
frame := &AckFrame{}
|
||||
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasMissingRanges := typeByte&0x20 == 0x20
|
||||
largestAckedLen := 2 * ((typeByte & 0x0C) >> 2)
|
||||
if largestAckedLen == 0 {
|
||||
largestAckedLen = 1
|
||||
}
|
||||
|
||||
missingSequenceNumberDeltaLen := 2 * (typeByte & 0x03)
|
||||
if missingSequenceNumberDeltaLen == 0 {
|
||||
missingSequenceNumberDeltaLen = 1
|
||||
}
|
||||
|
||||
la, err := utils.BigEndian.ReadUintN(r, largestAckedLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
largestAcked := protocol.PacketNumber(la)
|
||||
|
||||
delay, err := utils.BigEndian.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
|
||||
}
|
||||
}
|
||||
|
||||
if hasMissingRanges && numAckBlocks == 0 {
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
|
||||
abl, err := utils.BigEndian.ReadUintN(r, missingSequenceNumberDeltaLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ackBlockLength := protocol.PacketNumber(abl)
|
||||
if largestAcked > 0 && ackBlockLength < 1 {
|
||||
return nil, errors.New("invalid first ACK range")
|
||||
}
|
||||
|
||||
if ackBlockLength > largestAcked+1 {
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
|
||||
if hasMissingRanges {
|
||||
ackRange := AckRange{
|
||||
Smallest: largestAcked - ackBlockLength + 1,
|
||||
Largest: largestAcked,
|
||||
}
|
||||
frame.AckRanges = append(frame.AckRanges, ackRange)
|
||||
|
||||
var inLongBlock bool
|
||||
var lastRangeComplete bool
|
||||
for i := uint8(0); i < numAckBlocks; i++ {
|
||||
var gap uint8
|
||||
gap, err = r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
abl, err := utils.BigEndian.ReadUintN(r, missingSequenceNumberDeltaLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ackBlockLength := protocol.PacketNumber(abl)
|
||||
|
||||
if inLongBlock {
|
||||
frame.AckRanges[len(frame.AckRanges)-1].Smallest -= protocol.PacketNumber(gap) + ackBlockLength
|
||||
frame.AckRanges[len(frame.AckRanges)-1].Largest -= protocol.PacketNumber(gap)
|
||||
} else {
|
||||
lastRangeComplete = false
|
||||
ackRange := AckRange{
|
||||
Largest: frame.AckRanges[len(frame.AckRanges)-1].Smallest - protocol.PacketNumber(gap) - 1,
|
||||
}
|
||||
ackRange.Smallest = ackRange.Largest - ackBlockLength + 1
|
||||
frame.AckRanges = append(frame.AckRanges, ackRange)
|
||||
}
|
||||
|
||||
if ackBlockLength > 0 {
|
||||
lastRangeComplete = true
|
||||
}
|
||||
inLongBlock = (ackBlockLength == 0)
|
||||
}
|
||||
|
||||
// if the last range was not complete, First and Last make no sense
|
||||
// remove the range from frame.AckRanges
|
||||
if !lastRangeComplete {
|
||||
frame.AckRanges = frame.AckRanges[:len(frame.AckRanges)-1]
|
||||
}
|
||||
} else {
|
||||
frame.AckRanges = make([]AckRange, 1)
|
||||
if largestAcked != 0 {
|
||||
frame.AckRanges[0].Largest = largestAcked
|
||||
frame.AckRanges[0].Smallest = largestAcked + 1 - ackBlockLength
|
||||
}
|
||||
}
|
||||
|
||||
if !frame.validateAckRanges() {
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
|
||||
var numTimestamp byte
|
||||
numTimestamp, err = r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if numTimestamp > 0 {
|
||||
// Delta Largest acked
|
||||
_, err = r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// First Timestamp
|
||||
_, err = utils.BigEndian.ReadUint32(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < int(numTimestamp)-1; i++ {
|
||||
// Delta Largest acked
|
||||
_, err = r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Time Since Previous Timestamp
|
||||
_, err = utils.BigEndian.ReadUint16(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
func (f *AckFrame) writeLegacy(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
largestAcked := f.LargestAcked()
|
||||
largestAckedLen := protocol.GetPacketNumberLength(largestAcked)
|
||||
|
||||
typeByte := uint8(0x40)
|
||||
|
||||
if largestAckedLen != protocol.PacketNumberLen1 {
|
||||
typeByte ^= (uint8(largestAckedLen / 2)) << 2
|
||||
}
|
||||
|
||||
missingSequenceNumberDeltaLen := f.getMissingSequenceNumberDeltaLen()
|
||||
if missingSequenceNumberDeltaLen != protocol.PacketNumberLen1 {
|
||||
typeByte ^= (uint8(missingSequenceNumberDeltaLen / 2))
|
||||
}
|
||||
|
||||
if f.HasMissingRanges() {
|
||||
typeByte |= 0x20
|
||||
}
|
||||
|
||||
b.WriteByte(typeByte)
|
||||
|
||||
switch largestAckedLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(largestAcked))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.BigEndian.WriteUint16(b, uint16(largestAcked))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.BigEndian.WriteUint32(b, uint32(largestAcked))
|
||||
case protocol.PacketNumberLen6:
|
||||
utils.BigEndian.WriteUint48(b, uint64(largestAcked)&(1<<48-1))
|
||||
}
|
||||
|
||||
utils.BigEndian.WriteUfloat16(b, uint64(f.DelayTime/time.Microsecond))
|
||||
|
||||
var numRanges uint64
|
||||
var numRangesWritten uint64
|
||||
if f.HasMissingRanges() {
|
||||
numRanges = f.numWritableNackRanges()
|
||||
if numRanges > 0xFF {
|
||||
panic("AckFrame: Too many ACK ranges")
|
||||
}
|
||||
b.WriteByte(uint8(numRanges - 1))
|
||||
}
|
||||
|
||||
var firstAckBlockLength protocol.PacketNumber
|
||||
if !f.HasMissingRanges() {
|
||||
firstAckBlockLength = largestAcked - f.LowestAcked() + 1
|
||||
} else {
|
||||
firstAckBlockLength = largestAcked - f.AckRanges[0].Smallest + 1
|
||||
numRangesWritten++
|
||||
}
|
||||
|
||||
switch missingSequenceNumberDeltaLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(firstAckBlockLength))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.BigEndian.WriteUint16(b, uint16(firstAckBlockLength))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.BigEndian.WriteUint32(b, uint32(firstAckBlockLength))
|
||||
case protocol.PacketNumberLen6:
|
||||
utils.BigEndian.WriteUint48(b, uint64(firstAckBlockLength)&(1<<48-1))
|
||||
}
|
||||
|
||||
for i, ackRange := range f.AckRanges {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
length := ackRange.Largest - ackRange.Smallest + 1
|
||||
gap := f.AckRanges[i-1].Smallest - ackRange.Largest - 1
|
||||
|
||||
num := gap/0xFF + 1
|
||||
if gap%0xFF == 0 {
|
||||
num--
|
||||
}
|
||||
|
||||
if num == 1 {
|
||||
b.WriteByte(uint8(gap))
|
||||
switch missingSequenceNumberDeltaLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(length))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.BigEndian.WriteUint16(b, uint16(length))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.BigEndian.WriteUint32(b, uint32(length))
|
||||
case protocol.PacketNumberLen6:
|
||||
utils.BigEndian.WriteUint48(b, uint64(length)&(1<<48-1))
|
||||
}
|
||||
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(1 + ((gap - 1) % 255))
|
||||
} else {
|
||||
lengthWritten = 0
|
||||
gapWritten = 0xFF
|
||||
}
|
||||
|
||||
b.WriteByte(gapWritten)
|
||||
switch missingSequenceNumberDeltaLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(lengthWritten))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.BigEndian.WriteUint16(b, uint16(lengthWritten))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.BigEndian.WriteUint32(b, uint32(lengthWritten))
|
||||
case protocol.PacketNumberLen6:
|
||||
utils.BigEndian.WriteUint48(b, lengthWritten&(1<<48-1))
|
||||
}
|
||||
|
||||
numRangesWritten++
|
||||
}
|
||||
}
|
||||
|
||||
// this is needed if not all AckRanges can be written to the ACK frame (if there are more than 0xFF)
|
||||
if numRangesWritten >= numRanges {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if numRanges != numRangesWritten {
|
||||
return errors.New("BUG: Inconsistent number of ACK ranges written")
|
||||
}
|
||||
|
||||
b.WriteByte(0) // no timestamps
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *AckFrame) lengthLegacy(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
length := protocol.ByteCount(1 + 2 + 1) // 1 TypeByte, 2 ACK delay time, 1 Num Timestamp
|
||||
length += protocol.ByteCount(protocol.GetPacketNumberLength(f.LargestAcked()))
|
||||
|
||||
missingSequenceNumberDeltaLen := protocol.ByteCount(f.getMissingSequenceNumberDeltaLen())
|
||||
|
||||
if f.HasMissingRanges() {
|
||||
length += (1 + missingSequenceNumberDeltaLen) * protocol.ByteCount(f.numWritableNackRanges())
|
||||
} else {
|
||||
length += missingSequenceNumberDeltaLen
|
||||
}
|
||||
// we don't write
|
||||
return length
|
||||
}
|
||||
|
||||
// numWritableNackRanges 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 *AckFrame) numWritableNackRanges() 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.Smallest - ackRange.Largest - 1
|
||||
rangeLength := 1 + uint64(gap)/0xFF
|
||||
if uint64(gap)%0xFF == 0 {
|
||||
rangeLength--
|
||||
}
|
||||
|
||||
if numRanges+rangeLength < 0xFF {
|
||||
numRanges += rangeLength
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return numRanges + 1
|
||||
}
|
||||
|
||||
func (f *AckFrame) getMissingSequenceNumberDeltaLen() protocol.PacketNumberLen {
|
||||
var maxRangeLength protocol.PacketNumber
|
||||
|
||||
if f.HasMissingRanges() {
|
||||
for _, ackRange := range f.AckRanges {
|
||||
rangeLength := ackRange.Largest - ackRange.Smallest + 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
|
||||
}
|
||||
14
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_range.go
generated
vendored
Normal file
14
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_range.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package wire
|
||||
|
||||
import "github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
|
||||
// AckRange is an ACK range
|
||||
type AckRange struct {
|
||||
Smallest protocol.PacketNumber
|
||||
Largest protocol.PacketNumber
|
||||
}
|
||||
|
||||
// Len returns the number of packets contained in this ACK range
|
||||
func (r AckRange) Len() protocol.PacketNumber {
|
||||
return r.Largest - r.Smallest + 1
|
||||
}
|
||||
45
vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go
generated
vendored
Normal file
45
vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// A BlockedFrame is a BLOCKED frame
|
||||
type BlockedFrame struct {
|
||||
Offset protocol.ByteCount
|
||||
}
|
||||
|
||||
// parseBlockedFrame parses a BLOCKED frame
|
||||
func parseBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*BlockedFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &BlockedFrame{
|
||||
Offset: protocol.ByteCount(offset),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *BlockedFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return (&blockedFrameLegacy{}).Write(b, version)
|
||||
}
|
||||
typeByte := uint8(0x08)
|
||||
b.WriteByte(typeByte)
|
||||
utils.WriteVarInt(b, uint64(f.Offset))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *BlockedFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return 1 + 4
|
||||
}
|
||||
return 1 + utils.VarIntLen(uint64(f.Offset))
|
||||
}
|
||||
37
vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go
generated
vendored
Normal file
37
vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
type blockedFrameLegacy struct {
|
||||
StreamID protocol.StreamID
|
||||
}
|
||||
|
||||
// parseBlockedFrameLegacy parses a BLOCKED frame (in gQUIC format)
|
||||
// The frame returned is
|
||||
// * a STREAM_BLOCKED frame, if the BLOCKED applies to a stream
|
||||
// * a BLOCKED frame, if the BLOCKED applies to the connection
|
||||
func parseBlockedFrameLegacy(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) {
|
||||
if _, err := r.ReadByte(); err != nil { // read the TypeByte
|
||||
return nil, err
|
||||
}
|
||||
streamID, err := utils.BigEndian.ReadUint32(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if streamID == 0 {
|
||||
return &BlockedFrame{}, nil
|
||||
}
|
||||
return &StreamBlockedFrame{StreamID: protocol.StreamID(streamID)}, nil
|
||||
}
|
||||
|
||||
//Write writes a BLOCKED frame
|
||||
func (f *blockedFrameLegacy) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x05)
|
||||
utils.BigEndian.WriteUint32(b, uint32(f.StreamID))
|
||||
return nil
|
||||
}
|
||||
96
vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go
generated
vendored
Normal file
96
vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
)
|
||||
|
||||
// A ConnectionCloseFrame in QUIC
|
||||
type ConnectionCloseFrame struct {
|
||||
ErrorCode qerr.ErrorCode
|
||||
ReasonPhrase string
|
||||
}
|
||||
|
||||
// parseConnectionCloseFrame reads a CONNECTION_CLOSE frame
|
||||
func parseConnectionCloseFrame(r *bytes.Reader, version protocol.VersionNumber) (*ConnectionCloseFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil { // read the TypeByte
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var errorCode qerr.ErrorCode
|
||||
var reasonPhraseLen uint64
|
||||
if version.UsesIETFFrameFormat() {
|
||||
ec, err := utils.BigEndian.ReadUint16(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
errorCode = qerr.ErrorCode(ec)
|
||||
reasonPhraseLen, err = utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
ec, err := utils.BigEndian.ReadUint32(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
errorCode = qerr.ErrorCode(ec)
|
||||
length, err := utils.BigEndian.ReadUint16(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reasonPhraseLen = uint64(length)
|
||||
}
|
||||
|
||||
// shortcut to prevent the unnecessary allocation of dataLen bytes
|
||||
// if the dataLen is larger than the remaining length of the packet
|
||||
// reading the whole reason phrase would result in EOF when attempting to READ
|
||||
if int(reasonPhraseLen) > r.Len() {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
reasonPhrase := make([]byte, reasonPhraseLen)
|
||||
if _, err := io.ReadFull(r, reasonPhrase); err != nil {
|
||||
// this should never happen, since we already checked the reasonPhraseLen earlier
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ConnectionCloseFrame{
|
||||
ErrorCode: errorCode,
|
||||
ReasonPhrase: string(reasonPhrase),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *ConnectionCloseFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
if version.UsesIETFFrameFormat() {
|
||||
return 1 + 2 + utils.VarIntLen(uint64(len(f.ReasonPhrase))) + protocol.ByteCount(len(f.ReasonPhrase))
|
||||
}
|
||||
return 1 + 4 + 2 + protocol.ByteCount(len(f.ReasonPhrase))
|
||||
}
|
||||
|
||||
// Write writes an CONNECTION_CLOSE frame.
|
||||
func (f *ConnectionCloseFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
b.WriteByte(0x02)
|
||||
|
||||
if len(f.ReasonPhrase) > math.MaxUint16 {
|
||||
return errors.New("ConnectionFrame: ReasonPhrase too long")
|
||||
}
|
||||
|
||||
if version.UsesIETFFrameFormat() {
|
||||
utils.BigEndian.WriteUint16(b, uint16(f.ErrorCode))
|
||||
utils.WriteVarInt(b, uint64(len(f.ReasonPhrase)))
|
||||
} else {
|
||||
utils.BigEndian.WriteUint32(b, uint32(f.ErrorCode))
|
||||
utils.BigEndian.WriteUint16(b, uint16(len(f.ReasonPhrase)))
|
||||
}
|
||||
b.WriteString(f.ReasonPhrase)
|
||||
|
||||
return nil
|
||||
}
|
||||
13
vendor/github.com/lucas-clemente/quic-go/internal/wire/frame.go
generated
vendored
Normal file
13
vendor/github.com/lucas-clemente/quic-go/internal/wire/frame.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
// A Frame in QUIC
|
||||
type Frame interface {
|
||||
Write(b *bytes.Buffer, version protocol.VersionNumber) error
|
||||
Length(version protocol.VersionNumber) protocol.ByteCount
|
||||
}
|
||||
167
vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go
generated
vendored
Normal file
167
vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
)
|
||||
|
||||
// ParseNextFrame parses the next frame
|
||||
// It skips PADDING frames.
|
||||
func ParseNextFrame(r *bytes.Reader, hdr *Header, v protocol.VersionNumber) (Frame, error) {
|
||||
for r.Len() != 0 {
|
||||
typeByte, _ := r.ReadByte()
|
||||
if typeByte == 0x0 { // PADDING frame
|
||||
continue
|
||||
}
|
||||
r.UnreadByte()
|
||||
|
||||
if !v.UsesIETFFrameFormat() {
|
||||
return parseGQUICFrame(r, typeByte, hdr, v)
|
||||
}
|
||||
return parseIETFFrame(r, typeByte, v)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func parseIETFFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (Frame, error) {
|
||||
var frame Frame
|
||||
var err error
|
||||
if typeByte&0xf8 == 0x10 {
|
||||
frame, err = parseStreamFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidStreamData, err.Error())
|
||||
}
|
||||
return frame, err
|
||||
}
|
||||
// TODO: implement all IETF QUIC frame types
|
||||
switch typeByte {
|
||||
case 0x1:
|
||||
frame, err = parseRstStreamFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidRstStreamData, err.Error())
|
||||
}
|
||||
case 0x2:
|
||||
frame, err = parseConnectionCloseFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error())
|
||||
}
|
||||
case 0x4:
|
||||
frame, err = parseMaxDataFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
|
||||
}
|
||||
case 0x5:
|
||||
frame, err = parseMaxStreamDataFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
|
||||
}
|
||||
case 0x6:
|
||||
frame, err = parseMaxStreamIDFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidFrameData, err.Error())
|
||||
}
|
||||
case 0x7:
|
||||
frame, err = parsePingFrame(r, v)
|
||||
case 0x8:
|
||||
frame, err = parseBlockedFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidBlockedData, err.Error())
|
||||
}
|
||||
case 0x9:
|
||||
frame, err = parseStreamBlockedFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidBlockedData, err.Error())
|
||||
}
|
||||
case 0xa:
|
||||
frame, err = parseStreamIDBlockedFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidFrameData, err.Error())
|
||||
}
|
||||
case 0xc:
|
||||
frame, err = parseStopSendingFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidFrameData, err.Error())
|
||||
}
|
||||
case 0xe:
|
||||
frame, err = parsePathChallengeFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidFrameData, err.Error())
|
||||
}
|
||||
case 0xf:
|
||||
frame, err = parsePathResponseFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidFrameData, err.Error())
|
||||
}
|
||||
case 0x1a, 0x1b:
|
||||
frame, err = parseAckFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidAckData, err.Error())
|
||||
}
|
||||
default:
|
||||
err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
|
||||
}
|
||||
return frame, err
|
||||
}
|
||||
|
||||
func parseGQUICFrame(r *bytes.Reader, typeByte byte, hdr *Header, v protocol.VersionNumber) (Frame, error) {
|
||||
var frame Frame
|
||||
var err error
|
||||
if typeByte&0x80 == 0x80 {
|
||||
frame, err = parseStreamFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidStreamData, err.Error())
|
||||
}
|
||||
return frame, err
|
||||
} else if typeByte&0xc0 == 0x40 {
|
||||
frame, err = parseAckFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidAckData, err.Error())
|
||||
}
|
||||
return frame, err
|
||||
}
|
||||
switch typeByte {
|
||||
case 0x1:
|
||||
frame, err = parseRstStreamFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidRstStreamData, err.Error())
|
||||
}
|
||||
case 0x2:
|
||||
frame, err = parseConnectionCloseFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error())
|
||||
}
|
||||
case 0x3:
|
||||
frame, err = parseGoawayFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidGoawayData, err.Error())
|
||||
}
|
||||
case 0x4:
|
||||
frame, err = parseWindowUpdateFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
|
||||
}
|
||||
case 0x5:
|
||||
frame, err = parseBlockedFrameLegacy(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidBlockedData, err.Error())
|
||||
}
|
||||
case 0x6:
|
||||
if !v.UsesStopWaitingFrames() {
|
||||
err = errors.New("STOP_WAITING frames not supported by this QUIC version")
|
||||
break
|
||||
}
|
||||
frame, err = parseStopWaitingFrame(r, hdr.PacketNumber, hdr.PacketNumberLen, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidStopWaitingData, err.Error())
|
||||
}
|
||||
case 0x7:
|
||||
frame, err = parsePingFrame(r, v)
|
||||
default:
|
||||
err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
|
||||
}
|
||||
return frame, err
|
||||
}
|
||||
68
vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go
generated
vendored
Normal file
68
vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
)
|
||||
|
||||
// A GoawayFrame is a GOAWAY frame
|
||||
type GoawayFrame struct {
|
||||
ErrorCode qerr.ErrorCode
|
||||
LastGoodStream protocol.StreamID
|
||||
ReasonPhrase string
|
||||
}
|
||||
|
||||
// parseGoawayFrame parses a GOAWAY frame
|
||||
func parseGoawayFrame(r *bytes.Reader, _ protocol.VersionNumber) (*GoawayFrame, error) {
|
||||
frame := &GoawayFrame{}
|
||||
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
errorCode, err := utils.BigEndian.ReadUint32(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.ErrorCode = qerr.ErrorCode(errorCode)
|
||||
|
||||
lastGoodStream, err := utils.BigEndian.ReadUint32(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.LastGoodStream = protocol.StreamID(lastGoodStream)
|
||||
|
||||
reasonPhraseLen, err := utils.BigEndian.ReadUint16(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reasonPhraseLen > uint16(protocol.MaxReceivePacketSize) {
|
||||
return nil, qerr.Error(qerr.InvalidGoawayData, "reason phrase too long")
|
||||
}
|
||||
|
||||
reasonPhrase := make([]byte, reasonPhraseLen)
|
||||
if _, err := io.ReadFull(r, reasonPhrase); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.ReasonPhrase = string(reasonPhrase)
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
func (f *GoawayFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x03)
|
||||
utils.BigEndian.WriteUint32(b, uint32(f.ErrorCode))
|
||||
utils.BigEndian.WriteUint32(b, uint32(f.LastGoodStream))
|
||||
utils.BigEndian.WriteUint16(b, uint16(len(f.ReasonPhrase)))
|
||||
b.WriteString(f.ReasonPhrase)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *GoawayFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
return protocol.ByteCount(1 + 4 + 4 + 2 + len(f.ReasonPhrase))
|
||||
}
|
||||
333
vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go
generated
vendored
Normal file
333
vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go
generated
vendored
Normal file
@@ -0,0 +1,333 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// Header is the header of a QUIC packet.
|
||||
// It contains fields that are only needed for the gQUIC Public Header and the IETF draft Header.
|
||||
type Header struct {
|
||||
IsPublicHeader bool
|
||||
|
||||
Raw []byte
|
||||
|
||||
Version protocol.VersionNumber
|
||||
|
||||
DestConnectionID protocol.ConnectionID
|
||||
SrcConnectionID protocol.ConnectionID
|
||||
OrigDestConnectionID protocol.ConnectionID // only needed in the Retry packet
|
||||
|
||||
PacketNumberLen protocol.PacketNumberLen
|
||||
PacketNumber protocol.PacketNumber
|
||||
|
||||
IsVersionNegotiation bool
|
||||
SupportedVersions []protocol.VersionNumber // Version Number sent in a Version Negotiation Packet by the server
|
||||
|
||||
// only needed for the gQUIC Public Header
|
||||
VersionFlag bool
|
||||
ResetFlag bool
|
||||
DiversificationNonce []byte
|
||||
|
||||
// only needed for the IETF Header
|
||||
Type protocol.PacketType
|
||||
IsLongHeader bool
|
||||
KeyPhase int
|
||||
PayloadLen protocol.ByteCount
|
||||
Token []byte
|
||||
}
|
||||
|
||||
var errInvalidPacketNumberLen = errors.New("invalid packet number length")
|
||||
|
||||
// Write writes the Header.
|
||||
func (h *Header) Write(b *bytes.Buffer, pers protocol.Perspective, ver protocol.VersionNumber) error {
|
||||
if !ver.UsesIETFHeaderFormat() {
|
||||
h.IsPublicHeader = true // save that this is a Public Header, so we can log it correctly later
|
||||
return h.writePublicHeader(b, pers, ver)
|
||||
}
|
||||
// write an IETF QUIC header
|
||||
if h.IsLongHeader {
|
||||
return h.writeLongHeader(b, ver)
|
||||
}
|
||||
return h.writeShortHeader(b, ver)
|
||||
}
|
||||
|
||||
// TODO: add support for the key phase
|
||||
func (h *Header) writeLongHeader(b *bytes.Buffer, v protocol.VersionNumber) error {
|
||||
b.WriteByte(byte(0x80 | h.Type))
|
||||
utils.BigEndian.WriteUint32(b, uint32(h.Version))
|
||||
connIDLen, err := encodeConnIDLen(h.DestConnectionID, h.SrcConnectionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.WriteByte(connIDLen)
|
||||
b.Write(h.DestConnectionID.Bytes())
|
||||
b.Write(h.SrcConnectionID.Bytes())
|
||||
|
||||
if h.Type == protocol.PacketTypeInitial && v.UsesTokenInHeader() {
|
||||
utils.WriteVarInt(b, uint64(len(h.Token)))
|
||||
b.Write(h.Token)
|
||||
}
|
||||
|
||||
if h.Type == protocol.PacketTypeRetry {
|
||||
odcil, err := encodeSingleConnIDLen(h.OrigDestConnectionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// randomize the first 4 bits
|
||||
odcilByte := make([]byte, 1)
|
||||
_, _ = rand.Read(odcilByte) // it's safe to ignore the error here
|
||||
odcilByte[0] = (odcilByte[0] & 0xf0) | odcil
|
||||
b.Write(odcilByte)
|
||||
b.Write(h.OrigDestConnectionID.Bytes())
|
||||
b.Write(h.Token)
|
||||
return nil
|
||||
}
|
||||
|
||||
if v.UsesLengthInHeader() {
|
||||
utils.WriteVarInt(b, uint64(h.PayloadLen))
|
||||
}
|
||||
if v.UsesVarintPacketNumbers() {
|
||||
return utils.WriteVarIntPacketNumber(b, h.PacketNumber, h.PacketNumberLen)
|
||||
}
|
||||
utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
|
||||
if h.Type == protocol.PacketType0RTT && v == protocol.Version44 {
|
||||
if len(h.DiversificationNonce) != 32 {
|
||||
return errors.New("invalid diversification nonce length")
|
||||
}
|
||||
b.Write(h.DiversificationNonce)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Header) writeShortHeader(b *bytes.Buffer, v protocol.VersionNumber) error {
|
||||
typeByte := byte(0x30)
|
||||
typeByte |= byte(h.KeyPhase << 6)
|
||||
if !v.UsesVarintPacketNumbers() {
|
||||
switch h.PacketNumberLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
case protocol.PacketNumberLen2:
|
||||
typeByte |= 0x1
|
||||
case protocol.PacketNumberLen4:
|
||||
typeByte |= 0x2
|
||||
default:
|
||||
return errInvalidPacketNumberLen
|
||||
}
|
||||
}
|
||||
|
||||
b.WriteByte(typeByte)
|
||||
b.Write(h.DestConnectionID.Bytes())
|
||||
|
||||
if !v.UsesVarintPacketNumbers() {
|
||||
switch h.PacketNumberLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(h.PacketNumber))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.BigEndian.WriteUint16(b, uint16(h.PacketNumber))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return utils.WriteVarIntPacketNumber(b, h.PacketNumber, h.PacketNumberLen)
|
||||
}
|
||||
|
||||
// writePublicHeader writes a Public Header.
|
||||
func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _ protocol.VersionNumber) error {
|
||||
if h.ResetFlag || (h.VersionFlag && pers == protocol.PerspectiveServer) {
|
||||
return errors.New("PublicHeader: Can only write regular packets")
|
||||
}
|
||||
if h.SrcConnectionID.Len() != 0 {
|
||||
return errors.New("PublicHeader: SrcConnectionID must not be set")
|
||||
}
|
||||
if len(h.DestConnectionID) != 0 && len(h.DestConnectionID) != 8 {
|
||||
return fmt.Errorf("PublicHeader: wrong length for Connection ID: %d (expected 8)", len(h.DestConnectionID))
|
||||
}
|
||||
|
||||
publicFlagByte := uint8(0x00)
|
||||
if h.VersionFlag {
|
||||
publicFlagByte |= 0x01
|
||||
}
|
||||
if h.DestConnectionID.Len() > 0 {
|
||||
publicFlagByte |= 0x08
|
||||
}
|
||||
if len(h.DiversificationNonce) > 0 {
|
||||
if len(h.DiversificationNonce) != 32 {
|
||||
return errors.New("invalid diversification nonce length")
|
||||
}
|
||||
publicFlagByte |= 0x04
|
||||
}
|
||||
switch h.PacketNumberLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
publicFlagByte |= 0x00
|
||||
case protocol.PacketNumberLen2:
|
||||
publicFlagByte |= 0x10
|
||||
case protocol.PacketNumberLen4:
|
||||
publicFlagByte |= 0x20
|
||||
}
|
||||
b.WriteByte(publicFlagByte)
|
||||
|
||||
if h.DestConnectionID.Len() > 0 {
|
||||
b.Write(h.DestConnectionID)
|
||||
}
|
||||
if h.VersionFlag && pers == protocol.PerspectiveClient {
|
||||
utils.BigEndian.WriteUint32(b, uint32(h.Version))
|
||||
}
|
||||
if len(h.DiversificationNonce) > 0 {
|
||||
b.Write(h.DiversificationNonce)
|
||||
}
|
||||
|
||||
switch h.PacketNumberLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(h.PacketNumber))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.BigEndian.WriteUint16(b, uint16(h.PacketNumber))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
|
||||
case protocol.PacketNumberLen6:
|
||||
return errInvalidPacketNumberLen
|
||||
default:
|
||||
return errors.New("PublicHeader: PacketNumberLen not set")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetLength determines the length of the Header.
|
||||
func (h *Header) GetLength(v protocol.VersionNumber) (protocol.ByteCount, error) {
|
||||
if !v.UsesIETFHeaderFormat() {
|
||||
return h.getPublicHeaderLength()
|
||||
}
|
||||
return h.getHeaderLength(v)
|
||||
}
|
||||
|
||||
func (h *Header) getHeaderLength(v protocol.VersionNumber) (protocol.ByteCount, error) {
|
||||
if h.IsLongHeader {
|
||||
length := 1 /* type byte */ + 4 /* version */ + 1 /* conn id len byte */ + protocol.ByteCount(h.DestConnectionID.Len()+h.SrcConnectionID.Len()) + protocol.ByteCount(h.PacketNumberLen)
|
||||
if v.UsesLengthInHeader() {
|
||||
length += utils.VarIntLen(uint64(h.PayloadLen))
|
||||
}
|
||||
if h.Type == protocol.PacketTypeInitial && v.UsesTokenInHeader() {
|
||||
length += utils.VarIntLen(uint64(len(h.Token))) + protocol.ByteCount(len(h.Token))
|
||||
}
|
||||
if h.Type == protocol.PacketType0RTT && v == protocol.Version44 {
|
||||
length += protocol.ByteCount(len(h.DiversificationNonce))
|
||||
}
|
||||
return length, nil
|
||||
}
|
||||
|
||||
length := protocol.ByteCount(1 /* type byte */ + h.DestConnectionID.Len())
|
||||
if h.PacketNumberLen != protocol.PacketNumberLen1 && h.PacketNumberLen != protocol.PacketNumberLen2 && h.PacketNumberLen != protocol.PacketNumberLen4 {
|
||||
return 0, fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen)
|
||||
}
|
||||
length += protocol.ByteCount(h.PacketNumberLen)
|
||||
return length, nil
|
||||
}
|
||||
|
||||
// getPublicHeaderLength gets the length of the publicHeader in bytes.
|
||||
// It can only be called for regular packets.
|
||||
func (h *Header) getPublicHeaderLength() (protocol.ByteCount, error) {
|
||||
length := protocol.ByteCount(1) // 1 byte for public flags
|
||||
if h.PacketNumberLen == protocol.PacketNumberLen6 {
|
||||
return 0, errInvalidPacketNumberLen
|
||||
}
|
||||
if h.PacketNumberLen != protocol.PacketNumberLen1 && h.PacketNumberLen != protocol.PacketNumberLen2 && h.PacketNumberLen != protocol.PacketNumberLen4 {
|
||||
return 0, errPacketNumberLenNotSet
|
||||
}
|
||||
length += protocol.ByteCount(h.PacketNumberLen)
|
||||
length += protocol.ByteCount(h.DestConnectionID.Len())
|
||||
// Version Number in packets sent by the client
|
||||
if h.VersionFlag {
|
||||
length += 4
|
||||
}
|
||||
length += protocol.ByteCount(len(h.DiversificationNonce))
|
||||
return length, nil
|
||||
}
|
||||
|
||||
// Log logs the Header
|
||||
func (h *Header) Log(logger utils.Logger) {
|
||||
if h.IsPublicHeader {
|
||||
h.logPublicHeader(logger)
|
||||
} else {
|
||||
h.logHeader(logger)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Header) logHeader(logger utils.Logger) {
|
||||
if h.IsLongHeader {
|
||||
if h.Version == 0 {
|
||||
logger.Debugf("\tVersionNegotiationPacket{DestConnectionID: %s, SrcConnectionID: %s, SupportedVersions: %s}", h.DestConnectionID, h.SrcConnectionID, h.SupportedVersions)
|
||||
} else {
|
||||
var token string
|
||||
if h.Type == protocol.PacketTypeInitial || h.Type == protocol.PacketTypeRetry {
|
||||
if len(h.Token) == 0 {
|
||||
token = "Token: (empty), "
|
||||
} else {
|
||||
token = fmt.Sprintf("Token: %#x, ", h.Token)
|
||||
}
|
||||
}
|
||||
if h.Type == protocol.PacketTypeRetry {
|
||||
logger.Debugf("\tLong Header{Type: %s, DestConnectionID: %s, SrcConnectionID: %s, %sOrigDestConnectionID: %s, Version: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, token, h.OrigDestConnectionID, h.Version)
|
||||
return
|
||||
}
|
||||
if h.Version == protocol.Version44 {
|
||||
var divNonce string
|
||||
if h.Type == protocol.PacketType0RTT {
|
||||
divNonce = fmt.Sprintf("Diversification Nonce: %#x, ", h.DiversificationNonce)
|
||||
}
|
||||
logger.Debugf("\tLong Header{Type: %s, DestConnectionID: %s, SrcConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, %sVersion: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, h.PacketNumber, h.PacketNumberLen, divNonce, h.Version)
|
||||
return
|
||||
}
|
||||
logger.Debugf("\tLong Header{Type: %s, DestConnectionID: %s, SrcConnectionID: %s, %sPacketNumber: %#x, PacketNumberLen: %d, PayloadLen: %d, Version: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, token, h.PacketNumber, h.PacketNumberLen, h.PayloadLen, h.Version)
|
||||
}
|
||||
} else {
|
||||
logger.Debugf("\tShort Header{DestConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, KeyPhase: %d}", h.DestConnectionID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Header) logPublicHeader(logger utils.Logger) {
|
||||
ver := "(unset)"
|
||||
if h.Version != 0 {
|
||||
ver = h.Version.String()
|
||||
}
|
||||
logger.Debugf("\tPublic Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, Version: %s, DiversificationNonce: %#v}", h.DestConnectionID, h.PacketNumber, h.PacketNumberLen, ver, h.DiversificationNonce)
|
||||
}
|
||||
|
||||
func encodeConnIDLen(dest, src protocol.ConnectionID) (byte, error) {
|
||||
dcil, err := encodeSingleConnIDLen(dest)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
scil, err := encodeSingleConnIDLen(src)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return scil | dcil<<4, nil
|
||||
}
|
||||
|
||||
func encodeSingleConnIDLen(id protocol.ConnectionID) (byte, error) {
|
||||
len := id.Len()
|
||||
if len == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if len < 4 || len > 18 {
|
||||
return 0, fmt.Errorf("invalid connection ID length: %d bytes", len)
|
||||
}
|
||||
return byte(len - 3), nil
|
||||
}
|
||||
|
||||
func decodeConnIDLen(enc byte) (int /*dest conn id len*/, int /*src conn id len*/) {
|
||||
return decodeSingleConnIDLen(enc >> 4), decodeSingleConnIDLen(enc & 0xf)
|
||||
}
|
||||
|
||||
func decodeSingleConnIDLen(enc uint8) int {
|
||||
if enc == 0 {
|
||||
return 0
|
||||
}
|
||||
return int(enc) + 3
|
||||
}
|
||||
273
vendor/github.com/lucas-clemente/quic-go/internal/wire/header_parser.go
generated
vendored
Normal file
273
vendor/github.com/lucas-clemente/quic-go/internal/wire/header_parser.go
generated
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
)
|
||||
|
||||
// The InvariantHeader is the version independent part of the header
|
||||
type InvariantHeader struct {
|
||||
IsLongHeader bool
|
||||
Version protocol.VersionNumber
|
||||
SrcConnectionID protocol.ConnectionID
|
||||
DestConnectionID protocol.ConnectionID
|
||||
|
||||
typeByte byte
|
||||
}
|
||||
|
||||
// ParseInvariantHeader parses the version independent part of the header
|
||||
func ParseInvariantHeader(b *bytes.Reader, shortHeaderConnIDLen int) (*InvariantHeader, error) {
|
||||
typeByte, err := b.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
h := &InvariantHeader{typeByte: typeByte}
|
||||
h.IsLongHeader = typeByte&0x80 > 0
|
||||
|
||||
// If this is not a Long Header, it could either be a Public Header or a Short Header.
|
||||
if !h.IsLongHeader {
|
||||
// In the Public Header 0x8 is the Connection ID Flag.
|
||||
// In the IETF Short Header:
|
||||
// * 0x8 it is the gQUIC Demultiplexing bit, and always 0.
|
||||
// * 0x20 and 0x10 are always 1.
|
||||
var connIDLen int
|
||||
if typeByte&0x8 > 0 { // Public Header containing a connection ID
|
||||
connIDLen = 8
|
||||
}
|
||||
if typeByte&0x38 == 0x30 { // Short Header
|
||||
connIDLen = shortHeaderConnIDLen
|
||||
}
|
||||
if connIDLen > 0 {
|
||||
h.DestConnectionID, err = protocol.ReadConnectionID(b, connIDLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
// Long Header
|
||||
v, err := utils.BigEndian.ReadUint32(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.Version = protocol.VersionNumber(v)
|
||||
connIDLenByte, err := b.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dcil, scil := decodeConnIDLen(connIDLenByte)
|
||||
h.DestConnectionID, err = protocol.ReadConnectionID(b, dcil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.SrcConnectionID, err = protocol.ReadConnectionID(b, scil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// Parse parses the version dependent part of the header
|
||||
func (iv *InvariantHeader) Parse(b *bytes.Reader, sentBy protocol.Perspective, ver protocol.VersionNumber) (*Header, error) {
|
||||
if iv.IsLongHeader {
|
||||
if iv.Version == 0 { // Version Negotiation Packet
|
||||
return iv.parseVersionNegotiationPacket(b)
|
||||
}
|
||||
return iv.parseLongHeader(b, sentBy, ver)
|
||||
}
|
||||
// The Public Header never uses 6 byte packet numbers.
|
||||
// Therefore, the third and fourth bit will never be 11.
|
||||
// For the Short Header, the third and fourth bit are always 11.
|
||||
if iv.typeByte&0x30 != 0x30 {
|
||||
if sentBy == protocol.PerspectiveServer && iv.typeByte&0x1 > 0 {
|
||||
return iv.parseVersionNegotiationPacket(b)
|
||||
}
|
||||
return iv.parsePublicHeader(b, sentBy, ver)
|
||||
}
|
||||
return iv.parseShortHeader(b, ver)
|
||||
}
|
||||
|
||||
func (iv *InvariantHeader) toHeader() *Header {
|
||||
return &Header{
|
||||
IsLongHeader: iv.IsLongHeader,
|
||||
DestConnectionID: iv.DestConnectionID,
|
||||
SrcConnectionID: iv.SrcConnectionID,
|
||||
Version: iv.Version,
|
||||
}
|
||||
}
|
||||
|
||||
func (iv *InvariantHeader) parseVersionNegotiationPacket(b *bytes.Reader) (*Header, error) {
|
||||
h := iv.toHeader()
|
||||
h.VersionFlag = true
|
||||
if b.Len() == 0 {
|
||||
return nil, qerr.Error(qerr.InvalidVersionNegotiationPacket, "empty version list")
|
||||
}
|
||||
h.IsVersionNegotiation = true
|
||||
h.SupportedVersions = make([]protocol.VersionNumber, b.Len()/4)
|
||||
for i := 0; b.Len() > 0; i++ {
|
||||
v, err := utils.BigEndian.ReadUint32(b)
|
||||
if err != nil {
|
||||
return nil, qerr.InvalidVersionNegotiationPacket
|
||||
}
|
||||
h.SupportedVersions[i] = protocol.VersionNumber(v)
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (iv *InvariantHeader) parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, v protocol.VersionNumber) (*Header, error) {
|
||||
h := iv.toHeader()
|
||||
h.Type = protocol.PacketType(iv.typeByte & 0x7f)
|
||||
|
||||
if h.Type != protocol.PacketTypeInitial && h.Type != protocol.PacketTypeRetry && h.Type != protocol.PacketType0RTT && h.Type != protocol.PacketTypeHandshake {
|
||||
return nil, qerr.Error(qerr.InvalidPacketHeader, fmt.Sprintf("Received packet with invalid packet type: %d", h.Type))
|
||||
}
|
||||
|
||||
if h.Type == protocol.PacketTypeRetry {
|
||||
odcilByte, err := b.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
odcil := decodeSingleConnIDLen(odcilByte & 0xf)
|
||||
h.OrigDestConnectionID, err = protocol.ReadConnectionID(b, odcil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.Token = make([]byte, b.Len())
|
||||
if _, err := io.ReadFull(b, h.Token); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
if h.Type == protocol.PacketTypeInitial && v.UsesTokenInHeader() {
|
||||
tokenLen, err := utils.ReadVarInt(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tokenLen > uint64(b.Len()) {
|
||||
return nil, io.EOF
|
||||
}
|
||||
h.Token = make([]byte, tokenLen)
|
||||
if _, err := io.ReadFull(b, h.Token); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if v.UsesLengthInHeader() {
|
||||
pl, err := utils.ReadVarInt(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.PayloadLen = protocol.ByteCount(pl)
|
||||
}
|
||||
if v.UsesVarintPacketNumbers() {
|
||||
pn, pnLen, err := utils.ReadVarIntPacketNumber(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.PacketNumber = pn
|
||||
h.PacketNumberLen = pnLen
|
||||
} else {
|
||||
pn, err := utils.BigEndian.ReadUint32(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.PacketNumber = protocol.PacketNumber(pn)
|
||||
h.PacketNumberLen = protocol.PacketNumberLen4
|
||||
}
|
||||
if h.Type == protocol.PacketType0RTT && v == protocol.Version44 && sentBy == protocol.PerspectiveServer {
|
||||
h.DiversificationNonce = make([]byte, 32)
|
||||
if _, err := io.ReadFull(b, h.DiversificationNonce); err != nil {
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (iv *InvariantHeader) parseShortHeader(b *bytes.Reader, v protocol.VersionNumber) (*Header, error) {
|
||||
h := iv.toHeader()
|
||||
h.KeyPhase = int(iv.typeByte&0x40) >> 6
|
||||
|
||||
if v.UsesVarintPacketNumbers() {
|
||||
pn, pnLen, err := utils.ReadVarIntPacketNumber(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.PacketNumber = pn
|
||||
h.PacketNumberLen = pnLen
|
||||
} else {
|
||||
switch iv.typeByte & 0x3 {
|
||||
case 0x0:
|
||||
h.PacketNumberLen = protocol.PacketNumberLen1
|
||||
case 0x1:
|
||||
h.PacketNumberLen = protocol.PacketNumberLen2
|
||||
case 0x2:
|
||||
h.PacketNumberLen = protocol.PacketNumberLen4
|
||||
default:
|
||||
return nil, errInvalidPacketNumberLen
|
||||
}
|
||||
p, err := utils.BigEndian.ReadUintN(b, uint8(h.PacketNumberLen))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.PacketNumber = protocol.PacketNumber(p)
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (iv *InvariantHeader) parsePublicHeader(b *bytes.Reader, sentBy protocol.Perspective, ver protocol.VersionNumber) (*Header, error) {
|
||||
h := iv.toHeader()
|
||||
h.IsPublicHeader = true
|
||||
h.ResetFlag = iv.typeByte&0x2 > 0
|
||||
if h.ResetFlag {
|
||||
return h, nil
|
||||
}
|
||||
|
||||
h.VersionFlag = iv.typeByte&0x1 > 0
|
||||
if h.VersionFlag && sentBy == protocol.PerspectiveClient {
|
||||
v, err := utils.BigEndian.ReadUint32(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.Version = protocol.VersionNumber(v)
|
||||
}
|
||||
|
||||
// Contrary to what the gQUIC wire spec says, the 0x4 bit only indicates the presence of the diversification nonce for packets sent by the server.
|
||||
// It doesn't have any meaning when sent by the client.
|
||||
if sentBy == protocol.PerspectiveServer && iv.typeByte&0x4 > 0 {
|
||||
h.DiversificationNonce = make([]byte, 32)
|
||||
if _, err := io.ReadFull(b, h.DiversificationNonce); err != nil {
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
switch iv.typeByte & 0x30 {
|
||||
case 0x00:
|
||||
h.PacketNumberLen = protocol.PacketNumberLen1
|
||||
case 0x10:
|
||||
h.PacketNumberLen = protocol.PacketNumberLen2
|
||||
case 0x20:
|
||||
h.PacketNumberLen = protocol.PacketNumberLen4
|
||||
}
|
||||
|
||||
pn, err := utils.BigEndian.ReadUintN(b, uint8(h.PacketNumberLen))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.PacketNumber = protocol.PacketNumber(pn)
|
||||
|
||||
return h, nil
|
||||
}
|
||||
41
vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go
generated
vendored
Normal file
41
vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// LogFrame logs a frame, either sent or received
|
||||
func LogFrame(logger utils.Logger, frame Frame, sent bool) {
|
||||
if !logger.Debug() {
|
||||
return
|
||||
}
|
||||
dir := "<-"
|
||||
if sent {
|
||||
dir = "->"
|
||||
}
|
||||
switch f := frame.(type) {
|
||||
case *StreamFrame:
|
||||
logger.Debugf("\t%s &wire.StreamFrame{StreamID: %d, FinBit: %t, Offset: 0x%x, Data length: 0x%x, Offset + Data length: 0x%x}", dir, f.StreamID, f.FinBit, f.Offset, f.DataLen(), f.Offset+f.DataLen())
|
||||
case *StopWaitingFrame:
|
||||
if sent {
|
||||
logger.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x, PacketNumberLen: 0x%x}", dir, f.LeastUnacked, f.PacketNumberLen)
|
||||
} else {
|
||||
logger.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x}", dir, f.LeastUnacked)
|
||||
}
|
||||
case *AckFrame:
|
||||
if len(f.AckRanges) > 1 {
|
||||
ackRanges := make([]string, len(f.AckRanges))
|
||||
for i, r := range f.AckRanges {
|
||||
ackRanges[i] = fmt.Sprintf("{Largest: %#x, Smallest: %#x}", r.Largest, r.Smallest)
|
||||
}
|
||||
logger.Debugf("\t%s &wire.AckFrame{LargestAcked: %#x, LowestAcked: %#x, AckRanges: {%s}, DelayTime: %s}", dir, f.LargestAcked(), f.LowestAcked(), strings.Join(ackRanges, ", "), f.DelayTime.String())
|
||||
} else {
|
||||
logger.Debugf("\t%s &wire.AckFrame{LargestAcked: %#x, LowestAcked: %#x, DelayTime: %s}", dir, f.LargestAcked(), f.LowestAcked(), f.DelayTime.String())
|
||||
}
|
||||
default:
|
||||
logger.Debugf("\t%s %#v", dir, frame)
|
||||
}
|
||||
}
|
||||
51
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go
generated
vendored
Normal file
51
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// A MaxDataFrame carries flow control information for the connection
|
||||
type MaxDataFrame struct {
|
||||
ByteOffset protocol.ByteCount
|
||||
}
|
||||
|
||||
// parseMaxDataFrame parses a MAX_DATA frame
|
||||
func parseMaxDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxDataFrame, error) {
|
||||
// read the TypeByte
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
frame := &MaxDataFrame{}
|
||||
byteOffset, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.ByteOffset = protocol.ByteCount(byteOffset)
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
//Write writes a MAX_STREAM_DATA frame
|
||||
func (f *MaxDataFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
// write a gQUIC WINDOW_UPDATE frame (with stream ID 0, which means connection-level there)
|
||||
return (&windowUpdateFrame{
|
||||
StreamID: 0,
|
||||
ByteOffset: f.ByteOffset,
|
||||
}).Write(b, version)
|
||||
}
|
||||
b.WriteByte(0x4)
|
||||
utils.WriteVarInt(b, uint64(f.ByteOffset))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *MaxDataFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
if !version.UsesIETFFrameFormat() { // writing this frame would result in a gQUIC WINDOW_UPDATE being written, which is longer
|
||||
return 1 + 4 + 8
|
||||
}
|
||||
return 1 + utils.VarIntLen(uint64(f.ByteOffset))
|
||||
}
|
||||
60
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go
generated
vendored
Normal file
60
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// A MaxStreamDataFrame carries flow control information for a stream
|
||||
type MaxStreamDataFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
ByteOffset protocol.ByteCount
|
||||
}
|
||||
|
||||
// parseMaxStreamDataFrame parses a MAX_STREAM_DATA frame
|
||||
func parseMaxStreamDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxStreamDataFrame, error) {
|
||||
frame := &MaxStreamDataFrame{}
|
||||
|
||||
// read the TypeByte
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sid, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.StreamID = protocol.StreamID(sid)
|
||||
|
||||
byteOffset, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.ByteOffset = protocol.ByteCount(byteOffset)
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// Write writes a MAX_STREAM_DATA frame
|
||||
func (f *MaxStreamDataFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return (&windowUpdateFrame{
|
||||
StreamID: f.StreamID,
|
||||
ByteOffset: f.ByteOffset,
|
||||
}).Write(b, version)
|
||||
}
|
||||
b.WriteByte(0x5)
|
||||
utils.WriteVarInt(b, uint64(f.StreamID))
|
||||
utils.WriteVarInt(b, uint64(f.ByteOffset))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *MaxStreamDataFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
// writing this frame would result in a gQUIC WINDOW_UPDATE being written, which has a different length
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return 1 + 4 + 8
|
||||
}
|
||||
return 1 + utils.VarIntLen(uint64(f.StreamID)) + utils.VarIntLen(uint64(f.ByteOffset))
|
||||
}
|
||||
37
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go
generated
vendored
Normal file
37
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// A MaxStreamIDFrame is a MAX_STREAM_ID frame
|
||||
type MaxStreamIDFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
}
|
||||
|
||||
// parseMaxStreamIDFrame parses a MAX_STREAM_ID frame
|
||||
func parseMaxStreamIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamIDFrame, error) {
|
||||
// read the Type byte
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
streamID, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &MaxStreamIDFrame{StreamID: protocol.StreamID(streamID)}, nil
|
||||
}
|
||||
|
||||
func (f *MaxStreamIDFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x6)
|
||||
utils.WriteVarInt(b, uint64(f.StreamID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *MaxStreamIDFrame) Length(protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + utils.VarIntLen(uint64(f.StreamID))
|
||||
}
|
||||
39
vendor/github.com/lucas-clemente/quic-go/internal/wire/path_challenge_frame.go
generated
vendored
Normal file
39
vendor/github.com/lucas-clemente/quic-go/internal/wire/path_challenge_frame.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
// A PathChallengeFrame is a PATH_CHALLENGE frame
|
||||
type PathChallengeFrame struct {
|
||||
Data [8]byte
|
||||
}
|
||||
|
||||
func parsePathChallengeFrame(r *bytes.Reader, version protocol.VersionNumber) (*PathChallengeFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame := &PathChallengeFrame{}
|
||||
if _, err := io.ReadFull(r, frame.Data[:]); err != nil {
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
func (f *PathChallengeFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
typeByte := uint8(0x0e)
|
||||
b.WriteByte(typeByte)
|
||||
b.Write(f.Data[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *PathChallengeFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + 8
|
||||
}
|
||||
39
vendor/github.com/lucas-clemente/quic-go/internal/wire/path_response_frame.go
generated
vendored
Normal file
39
vendor/github.com/lucas-clemente/quic-go/internal/wire/path_response_frame.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
// A PathResponseFrame is a PATH_RESPONSE frame
|
||||
type PathResponseFrame struct {
|
||||
Data [8]byte
|
||||
}
|
||||
|
||||
func parsePathResponseFrame(r *bytes.Reader, version protocol.VersionNumber) (*PathResponseFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame := &PathResponseFrame{}
|
||||
if _, err := io.ReadFull(r, frame.Data[:]); err != nil {
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
func (f *PathResponseFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
typeByte := uint8(0x0f)
|
||||
b.WriteByte(typeByte)
|
||||
b.Write(f.Data[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *PathResponseFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + 8
|
||||
}
|
||||
33
vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go
generated
vendored
Normal file
33
vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
// A PingFrame is a ping frame
|
||||
type PingFrame struct{}
|
||||
|
||||
// parsePingFrame parses a Ping frame
|
||||
func parsePingFrame(r *bytes.Reader, version protocol.VersionNumber) (*PingFrame, error) {
|
||||
frame := &PingFrame{}
|
||||
|
||||
_, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
func (f *PingFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
typeByte := uint8(0x07)
|
||||
b.WriteByte(typeByte)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *PingFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1
|
||||
}
|
||||
65
vendor/github.com/lucas-clemente/quic-go/internal/wire/public_reset.go
generated
vendored
Normal file
65
vendor/github.com/lucas-clemente/quic-go/internal/wire/public_reset.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/handshake"
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// A PublicReset is a PUBLIC_RESET
|
||||
type PublicReset struct {
|
||||
RejectedPacketNumber protocol.PacketNumber
|
||||
Nonce uint64
|
||||
}
|
||||
|
||||
// WritePublicReset writes a PUBLIC_RESET
|
||||
func WritePublicReset(connectionID protocol.ConnectionID, rejectedPacketNumber protocol.PacketNumber, nonceProof uint64) []byte {
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteByte(0x0a)
|
||||
b.Write(connectionID)
|
||||
utils.LittleEndian.WriteUint32(b, uint32(handshake.TagPRST))
|
||||
utils.LittleEndian.WriteUint32(b, 2)
|
||||
utils.LittleEndian.WriteUint32(b, uint32(handshake.TagRNON))
|
||||
utils.LittleEndian.WriteUint32(b, 8)
|
||||
utils.LittleEndian.WriteUint32(b, uint32(handshake.TagRSEQ))
|
||||
utils.LittleEndian.WriteUint32(b, 16)
|
||||
utils.LittleEndian.WriteUint64(b, nonceProof)
|
||||
utils.LittleEndian.WriteUint64(b, uint64(rejectedPacketNumber))
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// ParsePublicReset parses a PUBLIC_RESET
|
||||
func ParsePublicReset(r *bytes.Reader) (*PublicReset, error) {
|
||||
pr := PublicReset{}
|
||||
msg, err := handshake.ParseHandshakeMessage(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if msg.Tag != handshake.TagPRST {
|
||||
return nil, errors.New("wrong public reset tag")
|
||||
}
|
||||
|
||||
// The RSEQ tag is mandatory according to the gQUIC wire spec.
|
||||
// However, Google doesn't send RSEQ in their PUBLIC_RESETs.
|
||||
// Therefore, we'll treat RSEQ as an optional field.
|
||||
if rseq, ok := msg.Data[handshake.TagRSEQ]; ok {
|
||||
if len(rseq) != 8 {
|
||||
return nil, errors.New("invalid RSEQ tag")
|
||||
}
|
||||
pr.RejectedPacketNumber = protocol.PacketNumber(binary.LittleEndian.Uint64(rseq))
|
||||
}
|
||||
|
||||
rnon, ok := msg.Data[handshake.TagRNON]
|
||||
if !ok {
|
||||
return nil, errors.New("RNON missing")
|
||||
}
|
||||
if len(rnon) != 8 {
|
||||
return nil, errors.New("invalid RNON tag")
|
||||
}
|
||||
pr.Nonce = binary.LittleEndian.Uint64(rnon)
|
||||
return &pr, nil
|
||||
}
|
||||
89
vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go
generated
vendored
Normal file
89
vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// A RstStreamFrame is a RST_STREAM frame in QUIC
|
||||
type RstStreamFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
// The error code is a uint32 in gQUIC, but a uint16 in IETF QUIC.
|
||||
// protocol.ApplicaitonErrorCode is a uint16, so larger values in gQUIC frames will be truncated.
|
||||
ErrorCode protocol.ApplicationErrorCode
|
||||
ByteOffset protocol.ByteCount
|
||||
}
|
||||
|
||||
// parseRstStreamFrame parses a RST_STREAM frame
|
||||
func parseRstStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*RstStreamFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil { // read the TypeByte
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var streamID protocol.StreamID
|
||||
var errorCode uint16
|
||||
var byteOffset protocol.ByteCount
|
||||
if version.UsesIETFFrameFormat() {
|
||||
sid, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
streamID = protocol.StreamID(sid)
|
||||
errorCode, err = utils.BigEndian.ReadUint16(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bo, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
byteOffset = protocol.ByteCount(bo)
|
||||
} else {
|
||||
sid, err := utils.BigEndian.ReadUint32(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
streamID = protocol.StreamID(sid)
|
||||
bo, err := utils.BigEndian.ReadUint64(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
byteOffset = protocol.ByteCount(bo)
|
||||
ec, err := utils.BigEndian.ReadUint32(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
errorCode = uint16(ec)
|
||||
}
|
||||
|
||||
return &RstStreamFrame{
|
||||
StreamID: streamID,
|
||||
ErrorCode: protocol.ApplicationErrorCode(errorCode),
|
||||
ByteOffset: byteOffset,
|
||||
}, nil
|
||||
}
|
||||
|
||||
//Write writes a RST_STREAM frame
|
||||
func (f *RstStreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
b.WriteByte(0x01)
|
||||
if version.UsesIETFFrameFormat() {
|
||||
utils.WriteVarInt(b, uint64(f.StreamID))
|
||||
utils.BigEndian.WriteUint16(b, uint16(f.ErrorCode))
|
||||
utils.WriteVarInt(b, uint64(f.ByteOffset))
|
||||
} else {
|
||||
utils.BigEndian.WriteUint32(b, uint32(f.StreamID))
|
||||
utils.BigEndian.WriteUint64(b, uint64(f.ByteOffset))
|
||||
utils.BigEndian.WriteUint32(b, uint32(f.ErrorCode))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *RstStreamFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
if version.UsesIETFFrameFormat() {
|
||||
return 1 + utils.VarIntLen(uint64(f.StreamID)) + 2 + utils.VarIntLen(uint64(f.ByteOffset))
|
||||
}
|
||||
return 1 + 4 + 8 + 4
|
||||
}
|
||||
47
vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go
generated
vendored
Normal file
47
vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// A StopSendingFrame is a STOP_SENDING frame
|
||||
type StopSendingFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
ErrorCode protocol.ApplicationErrorCode
|
||||
}
|
||||
|
||||
// parseStopSendingFrame parses a STOP_SENDING frame
|
||||
func parseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSendingFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil { // read the TypeByte
|
||||
return nil, err
|
||||
}
|
||||
|
||||
streamID, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
errorCode, err := utils.BigEndian.ReadUint16(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &StopSendingFrame{
|
||||
StreamID: protocol.StreamID(streamID),
|
||||
ErrorCode: protocol.ApplicationErrorCode(errorCode),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *StopSendingFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + utils.VarIntLen(uint64(f.StreamID)) + 2
|
||||
}
|
||||
|
||||
func (f *StopSendingFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x0c)
|
||||
utils.WriteVarInt(b, uint64(f.StreamID))
|
||||
utils.BigEndian.WriteUint16(b, uint16(f.ErrorCode))
|
||||
return nil
|
||||
}
|
||||
77
vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go
generated
vendored
Normal file
77
vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
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, v protocol.VersionNumber) error {
|
||||
if v.UsesIETFFrameFormat() {
|
||||
return errors.New("STOP_WAITING not defined in IETF QUIC")
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *StopWaitingFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + protocol.ByteCount(f.PacketNumberLen)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
52
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go
generated
vendored
Normal file
52
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// A StreamBlockedFrame in QUIC
|
||||
type StreamBlockedFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
Offset protocol.ByteCount
|
||||
}
|
||||
|
||||
// parseStreamBlockedFrame parses a STREAM_BLOCKED frame
|
||||
func parseStreamBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamBlockedFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil { // read the TypeByte
|
||||
return nil, err
|
||||
}
|
||||
sid, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &StreamBlockedFrame{
|
||||
StreamID: protocol.StreamID(sid),
|
||||
Offset: protocol.ByteCount(offset),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Write writes a STREAM_BLOCKED frame
|
||||
func (f *StreamBlockedFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return (&blockedFrameLegacy{StreamID: f.StreamID}).Write(b, version)
|
||||
}
|
||||
b.WriteByte(0x09)
|
||||
utils.WriteVarInt(b, uint64(f.StreamID))
|
||||
utils.WriteVarInt(b, uint64(f.Offset))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *StreamBlockedFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return 1 + 4
|
||||
}
|
||||
return 1 + utils.VarIntLen(uint64(f.StreamID)) + utils.VarIntLen(uint64(f.Offset))
|
||||
}
|
||||
179
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go
generated
vendored
Normal file
179
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
)
|
||||
|
||||
// A StreamFrame of QUIC
|
||||
type StreamFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
FinBit bool
|
||||
DataLenPresent bool
|
||||
Offset protocol.ByteCount
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// parseStreamFrame reads a STREAM frame
|
||||
func parseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamFrame, error) {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return parseLegacyStreamFrame(r, version)
|
||||
}
|
||||
|
||||
frame := &StreamFrame{}
|
||||
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
frame.FinBit = typeByte&0x1 > 0
|
||||
frame.DataLenPresent = typeByte&0x2 > 0
|
||||
hasOffset := typeByte&0x4 > 0
|
||||
|
||||
streamID, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.StreamID = protocol.StreamID(streamID)
|
||||
if hasOffset {
|
||||
offset, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.Offset = protocol.ByteCount(offset)
|
||||
}
|
||||
|
||||
var dataLen uint64
|
||||
if frame.DataLenPresent {
|
||||
var err error
|
||||
dataLen, err = utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// shortcut to prevent the unnecessary allocation of dataLen bytes
|
||||
// if the dataLen is larger than the remaining length of the packet
|
||||
// reading the packet contents would result in EOF when attempting to READ
|
||||
if dataLen > uint64(r.Len()) {
|
||||
return nil, io.EOF
|
||||
}
|
||||
} else {
|
||||
// The rest of the packet is data
|
||||
dataLen = uint64(r.Len())
|
||||
}
|
||||
if dataLen != 0 {
|
||||
frame.Data = make([]byte, dataLen)
|
||||
if _, err := io.ReadFull(r, frame.Data); err != nil {
|
||||
// this should never happen, since we already checked the dataLen earlier
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if frame.Offset+frame.DataLen() > protocol.MaxByteCount {
|
||||
return nil, qerr.Error(qerr.InvalidStreamData, "data overflows maximum offset")
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// Write writes a STREAM frame
|
||||
func (f *StreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return f.writeLegacy(b, version)
|
||||
}
|
||||
|
||||
if len(f.Data) == 0 && !f.FinBit {
|
||||
return errors.New("StreamFrame: attempting to write empty frame without FIN")
|
||||
}
|
||||
|
||||
typeByte := byte(0x10)
|
||||
if f.FinBit {
|
||||
typeByte ^= 0x1
|
||||
}
|
||||
hasOffset := f.Offset != 0
|
||||
if f.DataLenPresent {
|
||||
typeByte ^= 0x2
|
||||
}
|
||||
if hasOffset {
|
||||
typeByte ^= 0x4
|
||||
}
|
||||
b.WriteByte(typeByte)
|
||||
utils.WriteVarInt(b, uint64(f.StreamID))
|
||||
if hasOffset {
|
||||
utils.WriteVarInt(b, uint64(f.Offset))
|
||||
}
|
||||
if f.DataLenPresent {
|
||||
utils.WriteVarInt(b, uint64(f.DataLen()))
|
||||
}
|
||||
b.Write(f.Data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length returns the total length of the STREAM frame
|
||||
func (f *StreamFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return f.lengthLegacy(version)
|
||||
}
|
||||
length := 1 + utils.VarIntLen(uint64(f.StreamID))
|
||||
if f.Offset != 0 {
|
||||
length += utils.VarIntLen(uint64(f.Offset))
|
||||
}
|
||||
if f.DataLenPresent {
|
||||
length += utils.VarIntLen(uint64(f.DataLen()))
|
||||
}
|
||||
return length + f.DataLen()
|
||||
}
|
||||
|
||||
// MaxDataLen returns the maximum data length
|
||||
// If 0 is returned, writing will fail (a STREAM frame must contain at least 1 byte of data).
|
||||
func (f *StreamFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.VersionNumber) protocol.ByteCount {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return f.maxDataLenLegacy(maxSize, version)
|
||||
}
|
||||
|
||||
headerLen := 1 + utils.VarIntLen(uint64(f.StreamID))
|
||||
if f.Offset != 0 {
|
||||
headerLen += utils.VarIntLen(uint64(f.Offset))
|
||||
}
|
||||
if f.DataLenPresent {
|
||||
// pretend that the data size will be 1 bytes
|
||||
// if it turns out that varint encoding the length will consume 2 bytes, we need to adjust the data length afterwards
|
||||
headerLen++
|
||||
}
|
||||
if headerLen > maxSize {
|
||||
return 0
|
||||
}
|
||||
maxDataLen := maxSize - headerLen
|
||||
if f.DataLenPresent && utils.VarIntLen(uint64(maxDataLen)) != 1 {
|
||||
maxDataLen--
|
||||
}
|
||||
return maxDataLen
|
||||
}
|
||||
|
||||
// MaybeSplitOffFrame splits a frame such that it is not bigger than n bytes.
|
||||
// If n >= len(frame), nil is returned and nothing is modified.
|
||||
func (f *StreamFrame) MaybeSplitOffFrame(maxSize protocol.ByteCount, version protocol.VersionNumber) (*StreamFrame, error) {
|
||||
if maxSize >= f.Length(version) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
n := f.MaxDataLen(maxSize, version)
|
||||
if n == 0 {
|
||||
return nil, errors.New("too small")
|
||||
}
|
||||
newFrame := &StreamFrame{
|
||||
FinBit: false,
|
||||
StreamID: f.StreamID,
|
||||
Offset: f.Offset,
|
||||
Data: f.Data[:n],
|
||||
DataLenPresent: f.DataLenPresent,
|
||||
}
|
||||
|
||||
f.Data = f.Data[n:]
|
||||
f.Offset += n
|
||||
|
||||
return newFrame, nil
|
||||
}
|
||||
209
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame_legacy.go
generated
vendored
Normal file
209
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame_legacy.go
generated
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidStreamIDLen = errors.New("StreamFrame: Invalid StreamID length")
|
||||
errInvalidOffsetLen = errors.New("StreamFrame: Invalid offset length")
|
||||
)
|
||||
|
||||
// parseLegacyStreamFrame reads a stream frame. The type byte must not have been read yet.
|
||||
func parseLegacyStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamFrame, error) {
|
||||
frame := &StreamFrame{}
|
||||
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
frame.FinBit = typeByte&0x40 > 0
|
||||
frame.DataLenPresent = typeByte&0x20 > 0
|
||||
offsetLen := typeByte & 0x1c >> 2
|
||||
if offsetLen != 0 {
|
||||
offsetLen++
|
||||
}
|
||||
streamIDLen := typeByte&0x3 + 1
|
||||
|
||||
sid, err := utils.BigEndian.ReadUintN(r, streamIDLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.StreamID = protocol.StreamID(sid)
|
||||
|
||||
offset, err := utils.BigEndian.ReadUintN(r, offsetLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.Offset = protocol.ByteCount(offset)
|
||||
|
||||
var dataLen uint16
|
||||
if frame.DataLenPresent {
|
||||
dataLen, err = utils.BigEndian.ReadUint16(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// shortcut to prevent the unnecessary allocation of dataLen bytes
|
||||
// if the dataLen is larger than the remaining length of the packet
|
||||
// reading the packet contents would result in EOF when attempting to READ
|
||||
if int(dataLen) > r.Len() {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
if !frame.DataLenPresent {
|
||||
// The rest of the packet is data
|
||||
dataLen = uint16(r.Len())
|
||||
}
|
||||
if dataLen != 0 {
|
||||
frame.Data = make([]byte, dataLen)
|
||||
if _, err := io.ReadFull(r, frame.Data); err != nil {
|
||||
// this should never happen, since we already checked the dataLen earlier
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// MaxByteCount is the highest value that can be encoded with the IETF QUIC variable integer encoding (2^62-1).
|
||||
// Note that this value is smaller than the maximum value that could be encoded in the gQUIC STREAM frame (2^64-1).
|
||||
if frame.Offset+frame.DataLen() > protocol.MaxByteCount {
|
||||
return nil, qerr.Error(qerr.InvalidStreamData, "data overflows maximum offset")
|
||||
}
|
||||
if !frame.FinBit && frame.DataLen() == 0 {
|
||||
return nil, qerr.EmptyStreamFrameNoFin
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// writeLegacy writes a stream frame.
|
||||
func (f *StreamFrame) writeLegacy(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
if len(f.Data) == 0 && !f.FinBit {
|
||||
return errors.New("StreamFrame: attempting to write empty frame without FIN")
|
||||
}
|
||||
|
||||
typeByte := uint8(0x80) // sets the leftmost bit to 1
|
||||
if f.FinBit {
|
||||
typeByte ^= 0x40
|
||||
}
|
||||
if f.DataLenPresent {
|
||||
typeByte ^= 0x20
|
||||
}
|
||||
|
||||
offsetLength := f.getOffsetLength()
|
||||
if offsetLength > 0 {
|
||||
typeByte ^= (uint8(offsetLength) - 1) << 2
|
||||
}
|
||||
|
||||
streamIDLen := f.calculateStreamIDLength()
|
||||
typeByte ^= streamIDLen - 1
|
||||
|
||||
b.WriteByte(typeByte)
|
||||
|
||||
switch streamIDLen {
|
||||
case 1:
|
||||
b.WriteByte(uint8(f.StreamID))
|
||||
case 2:
|
||||
utils.BigEndian.WriteUint16(b, uint16(f.StreamID))
|
||||
case 3:
|
||||
utils.BigEndian.WriteUint24(b, uint32(f.StreamID))
|
||||
case 4:
|
||||
utils.BigEndian.WriteUint32(b, uint32(f.StreamID))
|
||||
default:
|
||||
return errInvalidStreamIDLen
|
||||
}
|
||||
|
||||
switch offsetLength {
|
||||
case 0:
|
||||
case 2:
|
||||
utils.BigEndian.WriteUint16(b, uint16(f.Offset))
|
||||
case 3:
|
||||
utils.BigEndian.WriteUint24(b, uint32(f.Offset))
|
||||
case 4:
|
||||
utils.BigEndian.WriteUint32(b, uint32(f.Offset))
|
||||
case 5:
|
||||
utils.BigEndian.WriteUint40(b, uint64(f.Offset))
|
||||
case 6:
|
||||
utils.BigEndian.WriteUint48(b, uint64(f.Offset))
|
||||
case 7:
|
||||
utils.BigEndian.WriteUint56(b, uint64(f.Offset))
|
||||
case 8:
|
||||
utils.BigEndian.WriteUint64(b, uint64(f.Offset))
|
||||
default:
|
||||
return errInvalidOffsetLen
|
||||
}
|
||||
|
||||
if f.DataLenPresent {
|
||||
utils.BigEndian.WriteUint16(b, uint16(len(f.Data)))
|
||||
}
|
||||
|
||||
b.Write(f.Data)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *StreamFrame) calculateStreamIDLength() uint8 {
|
||||
if f.StreamID < (1 << 8) {
|
||||
return 1
|
||||
} else if f.StreamID < (1 << 16) {
|
||||
return 2
|
||||
} else if f.StreamID < (1 << 24) {
|
||||
return 3
|
||||
}
|
||||
return 4
|
||||
}
|
||||
|
||||
func (f *StreamFrame) getOffsetLength() protocol.ByteCount {
|
||||
if f.Offset == 0 {
|
||||
return 0
|
||||
}
|
||||
if f.Offset < (1 << 16) {
|
||||
return 2
|
||||
}
|
||||
if f.Offset < (1 << 24) {
|
||||
return 3
|
||||
}
|
||||
if f.Offset < (1 << 32) {
|
||||
return 4
|
||||
}
|
||||
if f.Offset < (1 << 40) {
|
||||
return 5
|
||||
}
|
||||
if f.Offset < (1 << 48) {
|
||||
return 6
|
||||
}
|
||||
if f.Offset < (1 << 56) {
|
||||
return 7
|
||||
}
|
||||
return 8
|
||||
}
|
||||
|
||||
func (f *StreamFrame) headerLengthLegacy(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
length := protocol.ByteCount(1) + protocol.ByteCount(f.calculateStreamIDLength()) + f.getOffsetLength()
|
||||
if f.DataLenPresent {
|
||||
length += 2
|
||||
}
|
||||
return length
|
||||
}
|
||||
|
||||
func (f *StreamFrame) lengthLegacy(version protocol.VersionNumber) protocol.ByteCount {
|
||||
return f.headerLengthLegacy(version) + f.DataLen()
|
||||
}
|
||||
|
||||
func (f *StreamFrame) maxDataLenLegacy(maxFrameSize protocol.ByteCount, version protocol.VersionNumber) protocol.ByteCount {
|
||||
headerLen := f.headerLengthLegacy(version)
|
||||
if headerLen > maxFrameSize {
|
||||
return 0
|
||||
}
|
||||
return maxFrameSize - headerLen
|
||||
}
|
||||
|
||||
// DataLen gives the length of data in bytes
|
||||
func (f *StreamFrame) DataLen() protocol.ByteCount {
|
||||
return protocol.ByteCount(len(f.Data))
|
||||
}
|
||||
37
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go
generated
vendored
Normal file
37
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// A StreamIDBlockedFrame is a STREAM_ID_BLOCKED frame
|
||||
type StreamIDBlockedFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
}
|
||||
|
||||
// parseStreamIDBlockedFrame parses a STREAM_ID_BLOCKED frame
|
||||
func parseStreamIDBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamIDBlockedFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
streamID, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &StreamIDBlockedFrame{StreamID: protocol.StreamID(streamID)}, nil
|
||||
}
|
||||
|
||||
func (f *StreamIDBlockedFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
typeByte := uint8(0x0a)
|
||||
b.WriteByte(typeByte)
|
||||
utils.WriteVarInt(b, uint64(f.StreamID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *StreamIDBlockedFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + utils.VarIntLen(uint64(f.StreamID))
|
||||
}
|
||||
42
vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go
generated
vendored
Normal file
42
vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// ComposeGQUICVersionNegotiation composes a Version Negotiation Packet for gQUIC
|
||||
func ComposeGQUICVersionNegotiation(connID protocol.ConnectionID, versions []protocol.VersionNumber) []byte {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1+8+len(versions)*4))
|
||||
buf.Write([]byte{0x1 | 0x8}) // type byte
|
||||
buf.Write(connID)
|
||||
for _, v := range versions {
|
||||
utils.BigEndian.WriteUint32(buf, uint32(v))
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// ComposeVersionNegotiation composes a Version Negotiation according to the IETF draft
|
||||
func ComposeVersionNegotiation(destConnID, srcConnID protocol.ConnectionID, versions []protocol.VersionNumber) ([]byte, error) {
|
||||
greasedVersions := protocol.GetGreasedVersions(versions)
|
||||
expectedLen := 1 /* type byte */ + 4 /* version field */ + 1 /* connection ID length field */ + destConnID.Len() + srcConnID.Len() + len(greasedVersions)*4
|
||||
buf := bytes.NewBuffer(make([]byte, 0, expectedLen))
|
||||
r := make([]byte, 1)
|
||||
_, _ = rand.Read(r) // ignore the error here. It is not critical to have perfect random here.
|
||||
buf.WriteByte(r[0] | 0x80)
|
||||
utils.BigEndian.WriteUint32(buf, 0) // version 0
|
||||
connIDLen, err := encodeConnIDLen(destConnID, srcConnID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.WriteByte(connIDLen)
|
||||
buf.Write(destConnID)
|
||||
buf.Write(srcConnID)
|
||||
for _, v := range greasedVersions {
|
||||
utils.BigEndian.WriteUint32(buf, uint32(v))
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
45
vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go
generated
vendored
Normal file
45
vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
type windowUpdateFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
ByteOffset protocol.ByteCount
|
||||
}
|
||||
|
||||
// parseWindowUpdateFrame parses a WINDOW_UPDATE frame
|
||||
// The frame returned is
|
||||
// * a MAX_STREAM_DATA frame, if the WINDOW_UPDATE applies to a stream
|
||||
// * a MAX_DATA frame, if the WINDOW_UPDATE applies to the connection
|
||||
func parseWindowUpdateFrame(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) {
|
||||
if _, err := r.ReadByte(); err != nil { // read the TypeByte
|
||||
return nil, err
|
||||
}
|
||||
streamID, err := utils.BigEndian.ReadUint32(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err := utils.BigEndian.ReadUint64(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if streamID == 0 {
|
||||
return &MaxDataFrame{ByteOffset: protocol.ByteCount(offset)}, nil
|
||||
}
|
||||
return &MaxStreamDataFrame{
|
||||
StreamID: protocol.StreamID(streamID),
|
||||
ByteOffset: protocol.ByteCount(offset),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *windowUpdateFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x4)
|
||||
utils.BigEndian.WriteUint32(b, uint32(f.StreamID))
|
||||
utils.BigEndian.WriteUint64(b, uint64(f.ByteOffset))
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user