mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 06:09:58 +00:00
TUN-4597: Add a QUIC server skeleton
- Added a QUIC server to accept streams - Unit test for this server also tests ALPN - Temporary echo capability for HTTP ConnectionType
This commit is contained in:
251
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
generated
vendored
Normal file
251
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
generated
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
var errInvalidAckRanges = errors.New("AckFrame: ACK frame contains invalid ACK ranges")
|
||||
|
||||
// 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
|
||||
|
||||
ECT0, ECT1, ECNCE uint64
|
||||
}
|
||||
|
||||
// parseAckFrame reads an ACK frame
|
||||
func parseAckFrame(r *bytes.Reader, ackDelayExponent uint8, _ protocol.VersionNumber) (*AckFrame, error) {
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ecn := typeByte&0x1 > 0
|
||||
|
||||
frame := &AckFrame{}
|
||||
|
||||
la, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
largestAcked := protocol.PacketNumber(la)
|
||||
delay, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
delayTime := time.Duration(delay*1<<ackDelayExponent) * time.Microsecond
|
||||
if delayTime < 0 {
|
||||
// If the delay time overflows, set it to the maximum encodable value.
|
||||
delayTime = utils.InfDuration
|
||||
}
|
||||
frame.DelayTime = delayTime
|
||||
|
||||
numBlocks, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// read the first ACK range
|
||||
ab, err := quicvarint.Read(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 := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gap := protocol.PacketNumber(g)
|
||||
if smallest < gap+2 {
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
largest := smallest - gap - 2
|
||||
|
||||
ab, err := quicvarint.Read(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 := quicvarint.Read(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// Write writes an ACK frame.
|
||||
func (f *AckFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
hasECN := f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0
|
||||
if hasECN {
|
||||
b.WriteByte(0x3)
|
||||
} else {
|
||||
b.WriteByte(0x2)
|
||||
}
|
||||
quicvarint.Write(b, uint64(f.LargestAcked()))
|
||||
quicvarint.Write(b, encodeAckDelay(f.DelayTime))
|
||||
|
||||
numRanges := f.numEncodableAckRanges()
|
||||
quicvarint.Write(b, uint64(numRanges-1))
|
||||
|
||||
// write the first range
|
||||
_, firstRange := f.encodeAckRange(0)
|
||||
quicvarint.Write(b, firstRange)
|
||||
|
||||
// write all the other range
|
||||
for i := 1; i < numRanges; i++ {
|
||||
gap, len := f.encodeAckRange(i)
|
||||
quicvarint.Write(b, gap)
|
||||
quicvarint.Write(b, len)
|
||||
}
|
||||
|
||||
if hasECN {
|
||||
quicvarint.Write(b, f.ECT0)
|
||||
quicvarint.Write(b, f.ECT1)
|
||||
quicvarint.Write(b, f.ECNCE)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *AckFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
largestAcked := f.AckRanges[0].Largest
|
||||
numRanges := f.numEncodableAckRanges()
|
||||
|
||||
length := 1 + quicvarint.Len(uint64(largestAcked)) + quicvarint.Len(encodeAckDelay(f.DelayTime))
|
||||
|
||||
length += quicvarint.Len(uint64(numRanges - 1))
|
||||
lowestInFirstRange := f.AckRanges[0].Smallest
|
||||
length += quicvarint.Len(uint64(largestAcked - lowestInFirstRange))
|
||||
|
||||
for i := 1; i < numRanges; i++ {
|
||||
gap, len := f.encodeAckRange(i)
|
||||
length += quicvarint.Len(gap)
|
||||
length += quicvarint.Len(len)
|
||||
}
|
||||
if f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0 {
|
||||
length += quicvarint.Len(f.ECT0)
|
||||
length += quicvarint.Len(f.ECT1)
|
||||
length += quicvarint.Len(f.ECNCE)
|
||||
}
|
||||
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 + quicvarint.Len(uint64(f.LargestAcked())) + quicvarint.Len(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 := quicvarint.Len(gap) + quicvarint.Len(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 << protocol.AckDelayExponent)))
|
||||
}
|
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
|
||||
}
|
83
vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go
generated
vendored
Normal file
83
vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A ConnectionCloseFrame is a CONNECTION_CLOSE frame
|
||||
type ConnectionCloseFrame struct {
|
||||
IsApplicationError bool
|
||||
ErrorCode uint64
|
||||
FrameType uint64
|
||||
ReasonPhrase string
|
||||
}
|
||||
|
||||
func parseConnectionCloseFrame(r *bytes.Reader, _ protocol.VersionNumber) (*ConnectionCloseFrame, error) {
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := &ConnectionCloseFrame{IsApplicationError: typeByte == 0x1d}
|
||||
ec, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.ErrorCode = ec
|
||||
// read the Frame Type, if this is not an application error
|
||||
if !f.IsApplicationError {
|
||||
ft, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.FrameType = ft
|
||||
}
|
||||
var reasonPhraseLen uint64
|
||||
reasonPhraseLen, err = quicvarint.Read(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 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
|
||||
}
|
||||
f.ReasonPhrase = string(reasonPhrase)
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *ConnectionCloseFrame) Length(protocol.VersionNumber) protocol.ByteCount {
|
||||
length := 1 + quicvarint.Len(f.ErrorCode) + quicvarint.Len(uint64(len(f.ReasonPhrase))) + protocol.ByteCount(len(f.ReasonPhrase))
|
||||
if !f.IsApplicationError {
|
||||
length += quicvarint.Len(f.FrameType) // for the frame type
|
||||
}
|
||||
return length
|
||||
}
|
||||
|
||||
func (f *ConnectionCloseFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
if f.IsApplicationError {
|
||||
b.WriteByte(0x1d)
|
||||
} else {
|
||||
b.WriteByte(0x1c)
|
||||
}
|
||||
|
||||
quicvarint.Write(b, f.ErrorCode)
|
||||
if !f.IsApplicationError {
|
||||
quicvarint.Write(b, f.FrameType)
|
||||
}
|
||||
quicvarint.Write(b, uint64(len(f.ReasonPhrase)))
|
||||
b.WriteString(f.ReasonPhrase)
|
||||
return nil
|
||||
}
|
102
vendor/github.com/lucas-clemente/quic-go/internal/wire/crypto_frame.go
generated
vendored
Normal file
102
vendor/github.com/lucas-clemente/quic-go/internal/wire/crypto_frame.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A CryptoFrame is a CRYPTO frame
|
||||
type CryptoFrame struct {
|
||||
Offset protocol.ByteCount
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func parseCryptoFrame(r *bytes.Reader, _ protocol.VersionNumber) (*CryptoFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
frame := &CryptoFrame{}
|
||||
offset, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.Offset = protocol.ByteCount(offset)
|
||||
dataLen, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if dataLen > uint64(r.Len()) {
|
||||
return nil, io.EOF
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
func (f *CryptoFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x6)
|
||||
quicvarint.Write(b, uint64(f.Offset))
|
||||
quicvarint.Write(b, uint64(len(f.Data)))
|
||||
b.Write(f.Data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *CryptoFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(f.Offset)) + quicvarint.Len(uint64(len(f.Data))) + protocol.ByteCount(len(f.Data))
|
||||
}
|
||||
|
||||
// MaxDataLen returns the maximum data length
|
||||
func (f *CryptoFrame) MaxDataLen(maxSize protocol.ByteCount) protocol.ByteCount {
|
||||
// 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 := 1 + quicvarint.Len(uint64(f.Offset)) + 1
|
||||
if headerLen > maxSize {
|
||||
return 0
|
||||
}
|
||||
maxDataLen := maxSize - headerLen
|
||||
if quicvarint.Len(uint64(maxDataLen)) != 1 {
|
||||
maxDataLen--
|
||||
}
|
||||
return maxDataLen
|
||||
}
|
||||
|
||||
// MaybeSplitOffFrame splits a frame such that it is not bigger than n bytes.
|
||||
// It returns if the frame was actually split.
|
||||
// The frame might not be split if:
|
||||
// * the size is large enough to fit the whole frame
|
||||
// * the size is too small to fit even a 1-byte frame. In that case, the frame returned is nil.
|
||||
func (f *CryptoFrame) MaybeSplitOffFrame(maxSize protocol.ByteCount, version protocol.VersionNumber) (*CryptoFrame, bool /* was splitting required */) {
|
||||
if f.Length(version) <= maxSize {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
n := f.MaxDataLen(maxSize)
|
||||
if n == 0 {
|
||||
return nil, true
|
||||
}
|
||||
|
||||
newLen := protocol.ByteCount(len(f.Data)) - n
|
||||
|
||||
new := &CryptoFrame{}
|
||||
new.Offset = f.Offset
|
||||
new.Data = make([]byte, newLen)
|
||||
|
||||
// swap the data slices
|
||||
new.Data, f.Data = f.Data, new.Data
|
||||
|
||||
copy(f.Data, new.Data[n:])
|
||||
new.Data = new.Data[:n]
|
||||
f.Offset += n
|
||||
|
||||
return new, true
|
||||
}
|
38
vendor/github.com/lucas-clemente/quic-go/internal/wire/data_blocked_frame.go
generated
vendored
Normal file
38
vendor/github.com/lucas-clemente/quic-go/internal/wire/data_blocked_frame.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A DataBlockedFrame is a DATA_BLOCKED frame
|
||||
type DataBlockedFrame struct {
|
||||
MaximumData protocol.ByteCount
|
||||
}
|
||||
|
||||
func parseDataBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*DataBlockedFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &DataBlockedFrame{
|
||||
MaximumData: protocol.ByteCount(offset),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *DataBlockedFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
typeByte := uint8(0x14)
|
||||
b.WriteByte(typeByte)
|
||||
quicvarint.Write(b, uint64(f.MaximumData))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *DataBlockedFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(f.MaximumData))
|
||||
}
|
85
vendor/github.com/lucas-clemente/quic-go/internal/wire/datagram_frame.go
generated
vendored
Normal file
85
vendor/github.com/lucas-clemente/quic-go/internal/wire/datagram_frame.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A DatagramFrame is a DATAGRAM frame
|
||||
type DatagramFrame struct {
|
||||
DataLenPresent bool
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func parseDatagramFrame(r *bytes.Reader, _ protocol.VersionNumber) (*DatagramFrame, error) {
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := &DatagramFrame{}
|
||||
f.DataLenPresent = typeByte&0x1 > 0
|
||||
|
||||
var length uint64
|
||||
if f.DataLenPresent {
|
||||
var err error
|
||||
len, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len > uint64(r.Len()) {
|
||||
return nil, io.EOF
|
||||
}
|
||||
length = len
|
||||
} else {
|
||||
length = uint64(r.Len())
|
||||
}
|
||||
f.Data = make([]byte, length)
|
||||
if _, err := io.ReadFull(r, f.Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (f *DatagramFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
typeByte := uint8(0x30)
|
||||
if f.DataLenPresent {
|
||||
typeByte ^= 0x1
|
||||
}
|
||||
b.WriteByte(typeByte)
|
||||
if f.DataLenPresent {
|
||||
quicvarint.Write(b, uint64(len(f.Data)))
|
||||
}
|
||||
b.Write(f.Data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MaxDataLen returns the maximum data length
|
||||
func (f *DatagramFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.VersionNumber) protocol.ByteCount {
|
||||
headerLen := protocol.ByteCount(1)
|
||||
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 && quicvarint.Len(uint64(maxDataLen)) != 1 {
|
||||
maxDataLen--
|
||||
}
|
||||
return maxDataLen
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *DatagramFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
length := 1 + protocol.ByteCount(len(f.Data))
|
||||
if f.DataLenPresent {
|
||||
length += quicvarint.Len(uint64(len(f.Data)))
|
||||
}
|
||||
return length
|
||||
}
|
235
vendor/github.com/lucas-clemente/quic-go/internal/wire/extended_header.go
generated
vendored
Normal file
235
vendor/github.com/lucas-clemente/quic-go/internal/wire/extended_header.go
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// ErrInvalidReservedBits is returned when the reserved bits are incorrect.
|
||||
// When this error is returned, parsing continues, and an ExtendedHeader is returned.
|
||||
// This is necessary because we need to decrypt the packet in that case,
|
||||
// in order to avoid a timing side-channel.
|
||||
var ErrInvalidReservedBits = errors.New("invalid reserved bits")
|
||||
|
||||
// ExtendedHeader is the header of a QUIC packet.
|
||||
type ExtendedHeader struct {
|
||||
Header
|
||||
|
||||
typeByte byte
|
||||
|
||||
KeyPhase protocol.KeyPhaseBit
|
||||
|
||||
PacketNumberLen protocol.PacketNumberLen
|
||||
PacketNumber protocol.PacketNumber
|
||||
|
||||
parsedLen protocol.ByteCount
|
||||
}
|
||||
|
||||
func (h *ExtendedHeader) parse(b *bytes.Reader, v protocol.VersionNumber) (bool /* reserved bits valid */, error) {
|
||||
startLen := b.Len()
|
||||
// read the (now unencrypted) first byte
|
||||
var err error
|
||||
h.typeByte, err = b.ReadByte()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if _, err := b.Seek(int64(h.Header.ParsedLen())-1, io.SeekCurrent); err != nil {
|
||||
return false, err
|
||||
}
|
||||
var reservedBitsValid bool
|
||||
if h.IsLongHeader {
|
||||
reservedBitsValid, err = h.parseLongHeader(b, v)
|
||||
} else {
|
||||
reservedBitsValid, err = h.parseShortHeader(b, v)
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
h.parsedLen = protocol.ByteCount(startLen - b.Len())
|
||||
return reservedBitsValid, err
|
||||
}
|
||||
|
||||
func (h *ExtendedHeader) parseLongHeader(b *bytes.Reader, _ protocol.VersionNumber) (bool /* reserved bits valid */, error) {
|
||||
if err := h.readPacketNumber(b); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if h.typeByte&0xc != 0 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (h *ExtendedHeader) parseShortHeader(b *bytes.Reader, _ protocol.VersionNumber) (bool /* reserved bits valid */, error) {
|
||||
h.KeyPhase = protocol.KeyPhaseZero
|
||||
if h.typeByte&0x4 > 0 {
|
||||
h.KeyPhase = protocol.KeyPhaseOne
|
||||
}
|
||||
|
||||
if err := h.readPacketNumber(b); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if h.typeByte&0x18 != 0 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (h *ExtendedHeader) readPacketNumber(b *bytes.Reader) error {
|
||||
h.PacketNumberLen = protocol.PacketNumberLen(h.typeByte&0x3) + 1
|
||||
switch h.PacketNumberLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
n, err := b.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.PacketNumber = protocol.PacketNumber(n)
|
||||
case protocol.PacketNumberLen2:
|
||||
n, err := utils.BigEndian.ReadUint16(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.PacketNumber = protocol.PacketNumber(n)
|
||||
case protocol.PacketNumberLen3:
|
||||
n, err := utils.BigEndian.ReadUint24(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.PacketNumber = protocol.PacketNumber(n)
|
||||
case protocol.PacketNumberLen4:
|
||||
n, err := utils.BigEndian.ReadUint32(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.PacketNumber = protocol.PacketNumber(n)
|
||||
default:
|
||||
return fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write writes the Header.
|
||||
func (h *ExtendedHeader) Write(b *bytes.Buffer, ver protocol.VersionNumber) error {
|
||||
if h.DestConnectionID.Len() > protocol.MaxConnIDLen {
|
||||
return fmt.Errorf("invalid connection ID length: %d bytes", h.DestConnectionID.Len())
|
||||
}
|
||||
if h.SrcConnectionID.Len() > protocol.MaxConnIDLen {
|
||||
return fmt.Errorf("invalid connection ID length: %d bytes", h.SrcConnectionID.Len())
|
||||
}
|
||||
if h.IsLongHeader {
|
||||
return h.writeLongHeader(b, ver)
|
||||
}
|
||||
return h.writeShortHeader(b, ver)
|
||||
}
|
||||
|
||||
func (h *ExtendedHeader) writeLongHeader(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
var packetType uint8
|
||||
//nolint:exhaustive
|
||||
switch h.Type {
|
||||
case protocol.PacketTypeInitial:
|
||||
packetType = 0x0
|
||||
case protocol.PacketType0RTT:
|
||||
packetType = 0x1
|
||||
case protocol.PacketTypeHandshake:
|
||||
packetType = 0x2
|
||||
case protocol.PacketTypeRetry:
|
||||
packetType = 0x3
|
||||
}
|
||||
firstByte := 0xc0 | packetType<<4
|
||||
if h.Type != protocol.PacketTypeRetry {
|
||||
// Retry packets don't have a packet number
|
||||
firstByte |= uint8(h.PacketNumberLen - 1)
|
||||
}
|
||||
|
||||
b.WriteByte(firstByte)
|
||||
utils.BigEndian.WriteUint32(b, uint32(h.Version))
|
||||
b.WriteByte(uint8(h.DestConnectionID.Len()))
|
||||
b.Write(h.DestConnectionID.Bytes())
|
||||
b.WriteByte(uint8(h.SrcConnectionID.Len()))
|
||||
b.Write(h.SrcConnectionID.Bytes())
|
||||
|
||||
//nolint:exhaustive
|
||||
switch h.Type {
|
||||
case protocol.PacketTypeRetry:
|
||||
b.Write(h.Token)
|
||||
return nil
|
||||
case protocol.PacketTypeInitial:
|
||||
quicvarint.Write(b, uint64(len(h.Token)))
|
||||
b.Write(h.Token)
|
||||
}
|
||||
quicvarint.WriteWithLen(b, uint64(h.Length), 2)
|
||||
return h.writePacketNumber(b)
|
||||
}
|
||||
|
||||
func (h *ExtendedHeader) writeShortHeader(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
typeByte := 0x40 | uint8(h.PacketNumberLen-1)
|
||||
if h.KeyPhase == protocol.KeyPhaseOne {
|
||||
typeByte |= byte(1 << 2)
|
||||
}
|
||||
|
||||
b.WriteByte(typeByte)
|
||||
b.Write(h.DestConnectionID.Bytes())
|
||||
return h.writePacketNumber(b)
|
||||
}
|
||||
|
||||
func (h *ExtendedHeader) writePacketNumber(b *bytes.Buffer) error {
|
||||
switch h.PacketNumberLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
b.WriteByte(uint8(h.PacketNumber))
|
||||
case protocol.PacketNumberLen2:
|
||||
utils.BigEndian.WriteUint16(b, uint16(h.PacketNumber))
|
||||
case protocol.PacketNumberLen3:
|
||||
utils.BigEndian.WriteUint24(b, uint32(h.PacketNumber))
|
||||
case protocol.PacketNumberLen4:
|
||||
utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
|
||||
default:
|
||||
return fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParsedLen returns the number of bytes that were consumed when parsing the header
|
||||
func (h *ExtendedHeader) ParsedLen() protocol.ByteCount {
|
||||
return h.parsedLen
|
||||
}
|
||||
|
||||
// GetLength determines the length of the Header.
|
||||
func (h *ExtendedHeader) GetLength(v protocol.VersionNumber) protocol.ByteCount {
|
||||
if h.IsLongHeader {
|
||||
length := 1 /* type byte */ + 4 /* version */ + 1 /* dest conn ID len */ + protocol.ByteCount(h.DestConnectionID.Len()) + 1 /* src conn ID len */ + protocol.ByteCount(h.SrcConnectionID.Len()) + protocol.ByteCount(h.PacketNumberLen) + 2 /* length */
|
||||
if h.Type == protocol.PacketTypeInitial {
|
||||
length += quicvarint.Len(uint64(len(h.Token))) + protocol.ByteCount(len(h.Token))
|
||||
}
|
||||
return length
|
||||
}
|
||||
|
||||
length := protocol.ByteCount(1 /* type byte */ + h.DestConnectionID.Len())
|
||||
length += protocol.ByteCount(h.PacketNumberLen)
|
||||
return length
|
||||
}
|
||||
|
||||
// Log logs the Header
|
||||
func (h *ExtendedHeader) Log(logger utils.Logger) {
|
||||
if h.IsLongHeader {
|
||||
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, %sVersion: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, token, h.Version)
|
||||
return
|
||||
}
|
||||
}
|
||||
logger.Debugf("\tLong Header{Type: %s, DestConnectionID: %s, SrcConnectionID: %s, %sPacketNumber: %d, PacketNumberLen: %d, Length: %d, Version: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, token, h.PacketNumber, h.PacketNumberLen, h.Length, h.Version)
|
||||
} else {
|
||||
logger.Debugf("\tShort Header{DestConnectionID: %s, PacketNumber: %d, PacketNumberLen: %d, KeyPhase: %s}", h.DestConnectionID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase)
|
||||
}
|
||||
}
|
143
vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go
generated
vendored
Normal file
143
vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/qerr"
|
||||
)
|
||||
|
||||
type frameParser struct {
|
||||
ackDelayExponent uint8
|
||||
|
||||
supportsDatagrams bool
|
||||
|
||||
version protocol.VersionNumber
|
||||
}
|
||||
|
||||
// NewFrameParser creates a new frame parser.
|
||||
func NewFrameParser(supportsDatagrams bool, v protocol.VersionNumber) FrameParser {
|
||||
return &frameParser{
|
||||
supportsDatagrams: supportsDatagrams,
|
||||
version: v,
|
||||
}
|
||||
}
|
||||
|
||||
// ParseNext parses the next frame.
|
||||
// It skips PADDING frames.
|
||||
func (p *frameParser) ParseNext(r *bytes.Reader, encLevel protocol.EncryptionLevel) (Frame, error) {
|
||||
for r.Len() != 0 {
|
||||
typeByte, _ := r.ReadByte()
|
||||
if typeByte == 0x0 { // PADDING frame
|
||||
continue
|
||||
}
|
||||
r.UnreadByte()
|
||||
|
||||
f, err := p.parseFrame(r, typeByte, encLevel)
|
||||
if err != nil {
|
||||
return nil, &qerr.TransportError{
|
||||
FrameType: uint64(typeByte),
|
||||
ErrorCode: qerr.FrameEncodingError,
|
||||
ErrorMessage: err.Error(),
|
||||
}
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *frameParser) parseFrame(r *bytes.Reader, typeByte byte, encLevel protocol.EncryptionLevel) (Frame, error) {
|
||||
var frame Frame
|
||||
var err error
|
||||
if typeByte&0xf8 == 0x8 {
|
||||
frame, err = parseStreamFrame(r, p.version)
|
||||
} else {
|
||||
switch typeByte {
|
||||
case 0x1:
|
||||
frame, err = parsePingFrame(r, p.version)
|
||||
case 0x2, 0x3:
|
||||
ackDelayExponent := p.ackDelayExponent
|
||||
if encLevel != protocol.Encryption1RTT {
|
||||
ackDelayExponent = protocol.DefaultAckDelayExponent
|
||||
}
|
||||
frame, err = parseAckFrame(r, ackDelayExponent, p.version)
|
||||
case 0x4:
|
||||
frame, err = parseResetStreamFrame(r, p.version)
|
||||
case 0x5:
|
||||
frame, err = parseStopSendingFrame(r, p.version)
|
||||
case 0x6:
|
||||
frame, err = parseCryptoFrame(r, p.version)
|
||||
case 0x7:
|
||||
frame, err = parseNewTokenFrame(r, p.version)
|
||||
case 0x10:
|
||||
frame, err = parseMaxDataFrame(r, p.version)
|
||||
case 0x11:
|
||||
frame, err = parseMaxStreamDataFrame(r, p.version)
|
||||
case 0x12, 0x13:
|
||||
frame, err = parseMaxStreamsFrame(r, p.version)
|
||||
case 0x14:
|
||||
frame, err = parseDataBlockedFrame(r, p.version)
|
||||
case 0x15:
|
||||
frame, err = parseStreamDataBlockedFrame(r, p.version)
|
||||
case 0x16, 0x17:
|
||||
frame, err = parseStreamsBlockedFrame(r, p.version)
|
||||
case 0x18:
|
||||
frame, err = parseNewConnectionIDFrame(r, p.version)
|
||||
case 0x19:
|
||||
frame, err = parseRetireConnectionIDFrame(r, p.version)
|
||||
case 0x1a:
|
||||
frame, err = parsePathChallengeFrame(r, p.version)
|
||||
case 0x1b:
|
||||
frame, err = parsePathResponseFrame(r, p.version)
|
||||
case 0x1c, 0x1d:
|
||||
frame, err = parseConnectionCloseFrame(r, p.version)
|
||||
case 0x1e:
|
||||
frame, err = parseHandshakeDoneFrame(r, p.version)
|
||||
case 0x30, 0x31:
|
||||
if p.supportsDatagrams {
|
||||
frame, err = parseDatagramFrame(r, p.version)
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
err = errors.New("unknown frame type")
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !p.isAllowedAtEncLevel(frame, encLevel) {
|
||||
return nil, fmt.Errorf("%s not allowed at encryption level %s", reflect.TypeOf(frame).Elem().Name(), encLevel)
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
func (p *frameParser) isAllowedAtEncLevel(f Frame, encLevel protocol.EncryptionLevel) bool {
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial, protocol.EncryptionHandshake:
|
||||
switch f.(type) {
|
||||
case *CryptoFrame, *AckFrame, *ConnectionCloseFrame, *PingFrame:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case protocol.Encryption0RTT:
|
||||
switch f.(type) {
|
||||
case *CryptoFrame, *AckFrame, *ConnectionCloseFrame, *NewTokenFrame, *PathResponseFrame, *RetireConnectionIDFrame:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case protocol.Encryption1RTT:
|
||||
return true
|
||||
default:
|
||||
panic("unknown encryption level")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *frameParser) SetAckDelayExponent(exp uint8) {
|
||||
p.ackDelayExponent = exp
|
||||
}
|
28
vendor/github.com/lucas-clemente/quic-go/internal/wire/handshake_done_frame.go
generated
vendored
Normal file
28
vendor/github.com/lucas-clemente/quic-go/internal/wire/handshake_done_frame.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
// A HandshakeDoneFrame is a HANDSHAKE_DONE frame
|
||||
type HandshakeDoneFrame struct{}
|
||||
|
||||
// ParseHandshakeDoneFrame parses a HandshakeDone frame
|
||||
func parseHandshakeDoneFrame(r *bytes.Reader, _ protocol.VersionNumber) (*HandshakeDoneFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &HandshakeDoneFrame{}, nil
|
||||
}
|
||||
|
||||
func (f *HandshakeDoneFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x1e)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *HandshakeDoneFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1
|
||||
}
|
257
vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go
generated
vendored
Normal file
257
vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go
generated
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// ParseConnectionID parses the destination connection ID of a packet.
|
||||
// It uses the data slice for the connection ID.
|
||||
// That means that the connection ID must not be used after the packet buffer is released.
|
||||
func ParseConnectionID(data []byte, shortHeaderConnIDLen int) (protocol.ConnectionID, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
isLongHeader := data[0]&0x80 > 0
|
||||
if !isLongHeader {
|
||||
if len(data) < shortHeaderConnIDLen+1 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return protocol.ConnectionID(data[1 : 1+shortHeaderConnIDLen]), nil
|
||||
}
|
||||
if len(data) < 6 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
destConnIDLen := int(data[5])
|
||||
if len(data) < 6+destConnIDLen {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return protocol.ConnectionID(data[6 : 6+destConnIDLen]), nil
|
||||
}
|
||||
|
||||
// IsVersionNegotiationPacket says if this is a version negotiation packet
|
||||
func IsVersionNegotiationPacket(b []byte) bool {
|
||||
if len(b) < 5 {
|
||||
return false
|
||||
}
|
||||
return b[0]&0x80 > 0 && b[1] == 0 && b[2] == 0 && b[3] == 0 && b[4] == 0
|
||||
}
|
||||
|
||||
// Is0RTTPacket says if this is a 0-RTT packet.
|
||||
// A packet sent with a version we don't understand can never be a 0-RTT packet.
|
||||
func Is0RTTPacket(b []byte) bool {
|
||||
if len(b) < 5 {
|
||||
return false
|
||||
}
|
||||
if b[0]&0x80 == 0 {
|
||||
return false
|
||||
}
|
||||
if !protocol.IsSupportedVersion(protocol.SupportedVersions, protocol.VersionNumber(binary.BigEndian.Uint32(b[1:5]))) {
|
||||
return false
|
||||
}
|
||||
return b[0]&0x30>>4 == 0x1
|
||||
}
|
||||
|
||||
var ErrUnsupportedVersion = errors.New("unsupported version")
|
||||
|
||||
// The Header is the version independent part of the header
|
||||
type Header struct {
|
||||
IsLongHeader bool
|
||||
typeByte byte
|
||||
Type protocol.PacketType
|
||||
|
||||
Version protocol.VersionNumber
|
||||
SrcConnectionID protocol.ConnectionID
|
||||
DestConnectionID protocol.ConnectionID
|
||||
|
||||
Length protocol.ByteCount
|
||||
|
||||
Token []byte
|
||||
|
||||
parsedLen protocol.ByteCount // how many bytes were read while parsing this header
|
||||
}
|
||||
|
||||
// ParsePacket parses a packet.
|
||||
// If the packet has a long header, the packet is cut according to the length field.
|
||||
// If we understand the version, the packet is header up unto the packet number.
|
||||
// Otherwise, only the invariant part of the header is parsed.
|
||||
func ParsePacket(data []byte, shortHeaderConnIDLen int) (*Header, []byte /* packet data */, []byte /* rest */, error) {
|
||||
hdr, err := parseHeader(bytes.NewReader(data), shortHeaderConnIDLen)
|
||||
if err != nil {
|
||||
if err == ErrUnsupportedVersion {
|
||||
return hdr, nil, nil, ErrUnsupportedVersion
|
||||
}
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
var rest []byte
|
||||
if hdr.IsLongHeader {
|
||||
if protocol.ByteCount(len(data)) < hdr.ParsedLen()+hdr.Length {
|
||||
return nil, nil, nil, fmt.Errorf("packet length (%d bytes) is smaller than the expected length (%d bytes)", len(data)-int(hdr.ParsedLen()), hdr.Length)
|
||||
}
|
||||
packetLen := int(hdr.ParsedLen() + hdr.Length)
|
||||
rest = data[packetLen:]
|
||||
data = data[:packetLen]
|
||||
}
|
||||
return hdr, data, rest, nil
|
||||
}
|
||||
|
||||
// ParseHeader parses the header.
|
||||
// For short header packets: up to the packet number.
|
||||
// For long header packets:
|
||||
// * if we understand the version: up to the packet number
|
||||
// * if not, only the invariant part of the header
|
||||
func parseHeader(b *bytes.Reader, shortHeaderConnIDLen int) (*Header, error) {
|
||||
startLen := b.Len()
|
||||
h, err := parseHeaderImpl(b, shortHeaderConnIDLen)
|
||||
if err != nil {
|
||||
return h, err
|
||||
}
|
||||
h.parsedLen = protocol.ByteCount(startLen - b.Len())
|
||||
return h, err
|
||||
}
|
||||
|
||||
func parseHeaderImpl(b *bytes.Reader, shortHeaderConnIDLen int) (*Header, error) {
|
||||
typeByte, err := b.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
h := &Header{
|
||||
typeByte: typeByte,
|
||||
IsLongHeader: typeByte&0x80 > 0,
|
||||
}
|
||||
|
||||
if !h.IsLongHeader {
|
||||
if h.typeByte&0x40 == 0 {
|
||||
return nil, errors.New("not a QUIC packet")
|
||||
}
|
||||
if err := h.parseShortHeader(b, shortHeaderConnIDLen); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
return h, h.parseLongHeader(b)
|
||||
}
|
||||
|
||||
func (h *Header) parseShortHeader(b *bytes.Reader, shortHeaderConnIDLen int) error {
|
||||
var err error
|
||||
h.DestConnectionID, err = protocol.ReadConnectionID(b, shortHeaderConnIDLen)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Header) parseLongHeader(b *bytes.Reader) error {
|
||||
v, err := utils.BigEndian.ReadUint32(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.Version = protocol.VersionNumber(v)
|
||||
if h.Version != 0 && h.typeByte&0x40 == 0 {
|
||||
return errors.New("not a QUIC packet")
|
||||
}
|
||||
destConnIDLen, err := b.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.DestConnectionID, err = protocol.ReadConnectionID(b, int(destConnIDLen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srcConnIDLen, err := b.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.SrcConnectionID, err = protocol.ReadConnectionID(b, int(srcConnIDLen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if h.Version == 0 { // version negotiation packet
|
||||
return nil
|
||||
}
|
||||
// If we don't understand the version, we have no idea how to interpret the rest of the bytes
|
||||
if !protocol.IsSupportedVersion(protocol.SupportedVersions, h.Version) {
|
||||
return ErrUnsupportedVersion
|
||||
}
|
||||
|
||||
switch (h.typeByte & 0x30) >> 4 {
|
||||
case 0x0:
|
||||
h.Type = protocol.PacketTypeInitial
|
||||
case 0x1:
|
||||
h.Type = protocol.PacketType0RTT
|
||||
case 0x2:
|
||||
h.Type = protocol.PacketTypeHandshake
|
||||
case 0x3:
|
||||
h.Type = protocol.PacketTypeRetry
|
||||
}
|
||||
|
||||
if h.Type == protocol.PacketTypeRetry {
|
||||
tokenLen := b.Len() - 16
|
||||
if tokenLen <= 0 {
|
||||
return io.EOF
|
||||
}
|
||||
h.Token = make([]byte, tokenLen)
|
||||
if _, err := io.ReadFull(b, h.Token); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := b.Seek(16, io.SeekCurrent)
|
||||
return err
|
||||
}
|
||||
|
||||
if h.Type == protocol.PacketTypeInitial {
|
||||
tokenLen, err := quicvarint.Read(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tokenLen > uint64(b.Len()) {
|
||||
return io.EOF
|
||||
}
|
||||
h.Token = make([]byte, tokenLen)
|
||||
if _, err := io.ReadFull(b, h.Token); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
pl, err := quicvarint.Read(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.Length = protocol.ByteCount(pl)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParsedLen returns the number of bytes that were consumed when parsing the header
|
||||
func (h *Header) ParsedLen() protocol.ByteCount {
|
||||
return h.parsedLen
|
||||
}
|
||||
|
||||
// ParseExtended parses the version dependent part of the header.
|
||||
// The Reader has to be set such that it points to the first byte of the header.
|
||||
func (h *Header) ParseExtended(b *bytes.Reader, ver protocol.VersionNumber) (*ExtendedHeader, error) {
|
||||
extHdr := h.toExtendedHeader()
|
||||
reservedBitsValid, err := extHdr.parse(b, ver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !reservedBitsValid {
|
||||
return extHdr, ErrInvalidReservedBits
|
||||
}
|
||||
return extHdr, nil
|
||||
}
|
||||
|
||||
func (h *Header) toExtendedHeader() *ExtendedHeader {
|
||||
return &ExtendedHeader{Header: *h}
|
||||
}
|
||||
|
||||
// PacketType is the type of the packet, for logging purposes
|
||||
func (h *Header) PacketType() string {
|
||||
if h.IsLongHeader {
|
||||
return h.Type.String()
|
||||
}
|
||||
return "1-RTT"
|
||||
}
|
19
vendor/github.com/lucas-clemente/quic-go/internal/wire/interface.go
generated
vendored
Normal file
19
vendor/github.com/lucas-clemente/quic-go/internal/wire/interface.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
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
|
||||
}
|
||||
|
||||
// A FrameParser parses QUIC frames, one by one.
|
||||
type FrameParser interface {
|
||||
ParseNext(*bytes.Reader, protocol.EncryptionLevel) (Frame, error)
|
||||
SetAckDelayExponent(uint8)
|
||||
}
|
72
vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go
generated
vendored
Normal file
72
vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"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 *CryptoFrame:
|
||||
dataLen := protocol.ByteCount(len(f.Data))
|
||||
logger.Debugf("\t%s &wire.CryptoFrame{Offset: %d, Data length: %d, Offset + Data length: %d}", dir, f.Offset, dataLen, f.Offset+dataLen)
|
||||
case *StreamFrame:
|
||||
logger.Debugf("\t%s &wire.StreamFrame{StreamID: %d, Fin: %t, Offset: %d, Data length: %d, Offset + Data length: %d}", dir, f.StreamID, f.Fin, f.Offset, f.DataLen(), f.Offset+f.DataLen())
|
||||
case *ResetStreamFrame:
|
||||
logger.Debugf("\t%s &wire.ResetStreamFrame{StreamID: %d, ErrorCode: %#x, FinalSize: %d}", dir, f.StreamID, f.ErrorCode, f.FinalSize)
|
||||
case *AckFrame:
|
||||
hasECN := f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0
|
||||
var ecn string
|
||||
if hasECN {
|
||||
ecn = fmt.Sprintf(", ECT0: %d, ECT1: %d, CE: %d", f.ECT0, f.ECT1, f.ECNCE)
|
||||
}
|
||||
if len(f.AckRanges) > 1 {
|
||||
ackRanges := make([]string, len(f.AckRanges))
|
||||
for i, r := range f.AckRanges {
|
||||
ackRanges[i] = fmt.Sprintf("{Largest: %d, Smallest: %d}", r.Largest, r.Smallest)
|
||||
}
|
||||
logger.Debugf("\t%s &wire.AckFrame{LargestAcked: %d, LowestAcked: %d, AckRanges: {%s}, DelayTime: %s%s}", dir, f.LargestAcked(), f.LowestAcked(), strings.Join(ackRanges, ", "), f.DelayTime.String(), ecn)
|
||||
} else {
|
||||
logger.Debugf("\t%s &wire.AckFrame{LargestAcked: %d, LowestAcked: %d, DelayTime: %s%s}", dir, f.LargestAcked(), f.LowestAcked(), f.DelayTime.String(), ecn)
|
||||
}
|
||||
case *MaxDataFrame:
|
||||
logger.Debugf("\t%s &wire.MaxDataFrame{MaximumData: %d}", dir, f.MaximumData)
|
||||
case *MaxStreamDataFrame:
|
||||
logger.Debugf("\t%s &wire.MaxStreamDataFrame{StreamID: %d, MaximumStreamData: %d}", dir, f.StreamID, f.MaximumStreamData)
|
||||
case *DataBlockedFrame:
|
||||
logger.Debugf("\t%s &wire.DataBlockedFrame{MaximumData: %d}", dir, f.MaximumData)
|
||||
case *StreamDataBlockedFrame:
|
||||
logger.Debugf("\t%s &wire.StreamDataBlockedFrame{StreamID: %d, MaximumStreamData: %d}", dir, f.StreamID, f.MaximumStreamData)
|
||||
case *MaxStreamsFrame:
|
||||
switch f.Type {
|
||||
case protocol.StreamTypeUni:
|
||||
logger.Debugf("\t%s &wire.MaxStreamsFrame{Type: uni, MaxStreamNum: %d}", dir, f.MaxStreamNum)
|
||||
case protocol.StreamTypeBidi:
|
||||
logger.Debugf("\t%s &wire.MaxStreamsFrame{Type: bidi, MaxStreamNum: %d}", dir, f.MaxStreamNum)
|
||||
}
|
||||
case *StreamsBlockedFrame:
|
||||
switch f.Type {
|
||||
case protocol.StreamTypeUni:
|
||||
logger.Debugf("\t%s &wire.StreamsBlockedFrame{Type: uni, MaxStreams: %d}", dir, f.StreamLimit)
|
||||
case protocol.StreamTypeBidi:
|
||||
logger.Debugf("\t%s &wire.StreamsBlockedFrame{Type: bidi, MaxStreams: %d}", dir, f.StreamLimit)
|
||||
}
|
||||
case *NewConnectionIDFrame:
|
||||
logger.Debugf("\t%s &wire.NewConnectionIDFrame{SequenceNumber: %d, ConnectionID: %s, StatelessResetToken: %#x}", dir, f.SequenceNumber, f.ConnectionID, f.StatelessResetToken)
|
||||
case *NewTokenFrame:
|
||||
logger.Debugf("\t%s &wire.NewTokenFrame{Token: %#x}", dir, f.Token)
|
||||
default:
|
||||
logger.Debugf("\t%s %#v", dir, frame)
|
||||
}
|
||||
}
|
40
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go
generated
vendored
Normal file
40
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A MaxDataFrame carries flow control information for the connection
|
||||
type MaxDataFrame struct {
|
||||
MaximumData protocol.ByteCount
|
||||
}
|
||||
|
||||
// parseMaxDataFrame parses a MAX_DATA frame
|
||||
func parseMaxDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxDataFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
frame := &MaxDataFrame{}
|
||||
byteOffset, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.MaximumData = protocol.ByteCount(byteOffset)
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// Write writes a MAX_STREAM_DATA frame
|
||||
func (f *MaxDataFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
b.WriteByte(0x10)
|
||||
quicvarint.Write(b, uint64(f.MaximumData))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *MaxDataFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(f.MaximumData))
|
||||
}
|
46
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go
generated
vendored
Normal file
46
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A MaxStreamDataFrame is a MAX_STREAM_DATA frame
|
||||
type MaxStreamDataFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
MaximumStreamData protocol.ByteCount
|
||||
}
|
||||
|
||||
func parseMaxStreamDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamDataFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sid, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &MaxStreamDataFrame{
|
||||
StreamID: protocol.StreamID(sid),
|
||||
MaximumStreamData: protocol.ByteCount(offset),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *MaxStreamDataFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
b.WriteByte(0x11)
|
||||
quicvarint.Write(b, uint64(f.StreamID))
|
||||
quicvarint.Write(b, uint64(f.MaximumStreamData))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *MaxStreamDataFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.MaximumStreamData))
|
||||
}
|
55
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_streams_frame.go
generated
vendored
Normal file
55
vendor/github.com/lucas-clemente/quic-go/internal/wire/max_streams_frame.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A MaxStreamsFrame is a MAX_STREAMS frame
|
||||
type MaxStreamsFrame struct {
|
||||
Type protocol.StreamType
|
||||
MaxStreamNum protocol.StreamNum
|
||||
}
|
||||
|
||||
func parseMaxStreamsFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamsFrame, error) {
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := &MaxStreamsFrame{}
|
||||
switch typeByte {
|
||||
case 0x12:
|
||||
f.Type = protocol.StreamTypeBidi
|
||||
case 0x13:
|
||||
f.Type = protocol.StreamTypeUni
|
||||
}
|
||||
streamID, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.MaxStreamNum = protocol.StreamNum(streamID)
|
||||
if f.MaxStreamNum > protocol.MaxStreamCount {
|
||||
return nil, fmt.Errorf("%d exceeds the maximum stream count", f.MaxStreamNum)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (f *MaxStreamsFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
switch f.Type {
|
||||
case protocol.StreamTypeBidi:
|
||||
b.WriteByte(0x12)
|
||||
case protocol.StreamTypeUni:
|
||||
b.WriteByte(0x13)
|
||||
}
|
||||
quicvarint.Write(b, uint64(f.MaxStreamNum))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *MaxStreamsFrame) Length(protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(f.MaxStreamNum))
|
||||
}
|
80
vendor/github.com/lucas-clemente/quic-go/internal/wire/new_connection_id_frame.go
generated
vendored
Normal file
80
vendor/github.com/lucas-clemente/quic-go/internal/wire/new_connection_id_frame.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A NewConnectionIDFrame is a NEW_CONNECTION_ID frame
|
||||
type NewConnectionIDFrame struct {
|
||||
SequenceNumber uint64
|
||||
RetirePriorTo uint64
|
||||
ConnectionID protocol.ConnectionID
|
||||
StatelessResetToken protocol.StatelessResetToken
|
||||
}
|
||||
|
||||
func parseNewConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewConnectionIDFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
seq, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ret > seq {
|
||||
//nolint:stylecheck
|
||||
return nil, fmt.Errorf("Retire Prior To value (%d) larger than Sequence Number (%d)", ret, seq)
|
||||
}
|
||||
connIDLen, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if connIDLen > protocol.MaxConnIDLen {
|
||||
return nil, fmt.Errorf("invalid connection ID length: %d", connIDLen)
|
||||
}
|
||||
connID, err := protocol.ReadConnectionID(r, int(connIDLen))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame := &NewConnectionIDFrame{
|
||||
SequenceNumber: seq,
|
||||
RetirePriorTo: ret,
|
||||
ConnectionID: connID,
|
||||
}
|
||||
if _, err := io.ReadFull(r, frame.StatelessResetToken[:]); err != nil {
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
func (f *NewConnectionIDFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x18)
|
||||
quicvarint.Write(b, f.SequenceNumber)
|
||||
quicvarint.Write(b, f.RetirePriorTo)
|
||||
connIDLen := f.ConnectionID.Len()
|
||||
if connIDLen > protocol.MaxConnIDLen {
|
||||
return fmt.Errorf("invalid connection ID length: %d", connIDLen)
|
||||
}
|
||||
b.WriteByte(uint8(connIDLen))
|
||||
b.Write(f.ConnectionID.Bytes())
|
||||
b.Write(f.StatelessResetToken[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *NewConnectionIDFrame) Length(protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(f.SequenceNumber) + quicvarint.Len(f.RetirePriorTo) + 1 /* connection ID length */ + protocol.ByteCount(f.ConnectionID.Len()) + 16
|
||||
}
|
48
vendor/github.com/lucas-clemente/quic-go/internal/wire/new_token_frame.go
generated
vendored
Normal file
48
vendor/github.com/lucas-clemente/quic-go/internal/wire/new_token_frame.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A NewTokenFrame is a NEW_TOKEN frame
|
||||
type NewTokenFrame struct {
|
||||
Token []byte
|
||||
}
|
||||
|
||||
func parseNewTokenFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewTokenFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tokenLen, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uint64(r.Len()) < tokenLen {
|
||||
return nil, io.EOF
|
||||
}
|
||||
if tokenLen == 0 {
|
||||
return nil, errors.New("token must not be empty")
|
||||
}
|
||||
token := make([]byte, int(tokenLen))
|
||||
if _, err := io.ReadFull(r, token); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &NewTokenFrame{Token: token}, nil
|
||||
}
|
||||
|
||||
func (f *NewTokenFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x7)
|
||||
quicvarint.Write(b, uint64(len(f.Token)))
|
||||
b.Write(f.Token)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *NewTokenFrame) Length(protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(len(f.Token))) + protocol.ByteCount(len(f.Token))
|
||||
}
|
38
vendor/github.com/lucas-clemente/quic-go/internal/wire/path_challenge_frame.go
generated
vendored
Normal file
38
vendor/github.com/lucas-clemente/quic-go/internal/wire/path_challenge_frame.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
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, _ 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 {
|
||||
b.WriteByte(0x1a)
|
||||
b.Write(f.Data[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *PathChallengeFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + 8
|
||||
}
|
38
vendor/github.com/lucas-clemente/quic-go/internal/wire/path_response_frame.go
generated
vendored
Normal file
38
vendor/github.com/lucas-clemente/quic-go/internal/wire/path_response_frame.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
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, _ 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 {
|
||||
b.WriteByte(0x1b)
|
||||
b.Write(f.Data[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *PathResponseFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + 8
|
||||
}
|
27
vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go
generated
vendored
Normal file
27
vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
// A PingFrame is a PING frame
|
||||
type PingFrame struct{}
|
||||
|
||||
func parsePingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PingFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PingFrame{}, nil
|
||||
}
|
||||
|
||||
func (f *PingFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
b.WriteByte(0x1)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *PingFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1
|
||||
}
|
33
vendor/github.com/lucas-clemente/quic-go/internal/wire/pool.go
generated
vendored
Normal file
33
vendor/github.com/lucas-clemente/quic-go/internal/wire/pool.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
var pool sync.Pool
|
||||
|
||||
func init() {
|
||||
pool.New = func() interface{} {
|
||||
return &StreamFrame{
|
||||
Data: make([]byte, 0, protocol.MaxPacketBufferSize),
|
||||
fromPool: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetStreamFrame() *StreamFrame {
|
||||
f := pool.Get().(*StreamFrame)
|
||||
return f
|
||||
}
|
||||
|
||||
func putStreamFrame(f *StreamFrame) {
|
||||
if !f.fromPool {
|
||||
return
|
||||
}
|
||||
if protocol.ByteCount(cap(f.Data)) != protocol.MaxPacketBufferSize {
|
||||
panic("wire.PutStreamFrame called with packet of wrong size!")
|
||||
}
|
||||
pool.Put(f)
|
||||
}
|
58
vendor/github.com/lucas-clemente/quic-go/internal/wire/reset_stream_frame.go
generated
vendored
Normal file
58
vendor/github.com/lucas-clemente/quic-go/internal/wire/reset_stream_frame.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/qerr"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A ResetStreamFrame is a RESET_STREAM frame in QUIC
|
||||
type ResetStreamFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
ErrorCode qerr.StreamErrorCode
|
||||
FinalSize protocol.ByteCount
|
||||
}
|
||||
|
||||
func parseResetStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*ResetStreamFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil { // read the TypeByte
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var streamID protocol.StreamID
|
||||
var byteOffset protocol.ByteCount
|
||||
sid, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
streamID = protocol.StreamID(sid)
|
||||
errorCode, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bo, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
byteOffset = protocol.ByteCount(bo)
|
||||
|
||||
return &ResetStreamFrame{
|
||||
StreamID: streamID,
|
||||
ErrorCode: qerr.StreamErrorCode(errorCode),
|
||||
FinalSize: byteOffset,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *ResetStreamFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x4)
|
||||
quicvarint.Write(b, uint64(f.StreamID))
|
||||
quicvarint.Write(b, uint64(f.ErrorCode))
|
||||
quicvarint.Write(b, uint64(f.FinalSize))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *ResetStreamFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.ErrorCode)) + quicvarint.Len(uint64(f.FinalSize))
|
||||
}
|
36
vendor/github.com/lucas-clemente/quic-go/internal/wire/retire_connection_id_frame.go
generated
vendored
Normal file
36
vendor/github.com/lucas-clemente/quic-go/internal/wire/retire_connection_id_frame.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A RetireConnectionIDFrame is a RETIRE_CONNECTION_ID frame
|
||||
type RetireConnectionIDFrame struct {
|
||||
SequenceNumber uint64
|
||||
}
|
||||
|
||||
func parseRetireConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*RetireConnectionIDFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
seq, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &RetireConnectionIDFrame{SequenceNumber: seq}, nil
|
||||
}
|
||||
|
||||
func (f *RetireConnectionIDFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x19)
|
||||
quicvarint.Write(b, f.SequenceNumber)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *RetireConnectionIDFrame) Length(protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(f.SequenceNumber)
|
||||
}
|
48
vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go
generated
vendored
Normal file
48
vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/qerr"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A StopSendingFrame is a STOP_SENDING frame
|
||||
type StopSendingFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
ErrorCode qerr.StreamErrorCode
|
||||
}
|
||||
|
||||
// parseStopSendingFrame parses a STOP_SENDING frame
|
||||
func parseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSendingFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
streamID, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
errorCode, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &StopSendingFrame{
|
||||
StreamID: protocol.StreamID(streamID),
|
||||
ErrorCode: qerr.StreamErrorCode(errorCode),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *StopSendingFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.ErrorCode))
|
||||
}
|
||||
|
||||
func (f *StopSendingFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
b.WriteByte(0x5)
|
||||
quicvarint.Write(b, uint64(f.StreamID))
|
||||
quicvarint.Write(b, uint64(f.ErrorCode))
|
||||
return nil
|
||||
}
|
46
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_data_blocked_frame.go
generated
vendored
Normal file
46
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_data_blocked_frame.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A StreamDataBlockedFrame is a STREAM_DATA_BLOCKED frame
|
||||
type StreamDataBlockedFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
MaximumStreamData protocol.ByteCount
|
||||
}
|
||||
|
||||
func parseStreamDataBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamDataBlockedFrame, error) {
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sid, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &StreamDataBlockedFrame{
|
||||
StreamID: protocol.StreamID(sid),
|
||||
MaximumStreamData: protocol.ByteCount(offset),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *StreamDataBlockedFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
b.WriteByte(0x15)
|
||||
quicvarint.Write(b, uint64(f.StreamID))
|
||||
quicvarint.Write(b, uint64(f.MaximumStreamData))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *StreamDataBlockedFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.MaximumStreamData))
|
||||
}
|
189
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go
generated
vendored
Normal file
189
vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go
generated
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A StreamFrame of QUIC
|
||||
type StreamFrame struct {
|
||||
StreamID protocol.StreamID
|
||||
Offset protocol.ByteCount
|
||||
Data []byte
|
||||
Fin bool
|
||||
DataLenPresent bool
|
||||
|
||||
fromPool bool
|
||||
}
|
||||
|
||||
func parseStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamFrame, error) {
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasOffset := typeByte&0x4 > 0
|
||||
fin := typeByte&0x1 > 0
|
||||
hasDataLen := typeByte&0x2 > 0
|
||||
|
||||
streamID, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var offset uint64
|
||||
if hasOffset {
|
||||
offset, err = quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var dataLen uint64
|
||||
if hasDataLen {
|
||||
var err error
|
||||
dataLen, err = quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// The rest of the packet is data
|
||||
dataLen = uint64(r.Len())
|
||||
}
|
||||
|
||||
var frame *StreamFrame
|
||||
if dataLen < protocol.MinStreamFrameBufferSize {
|
||||
frame = &StreamFrame{Data: make([]byte, dataLen)}
|
||||
} else {
|
||||
frame = GetStreamFrame()
|
||||
// The STREAM frame can't be larger than the StreamFrame we obtained from the buffer,
|
||||
// since those StreamFrames have a buffer length of the maximum packet size.
|
||||
if dataLen > uint64(cap(frame.Data)) {
|
||||
return nil, io.EOF
|
||||
}
|
||||
frame.Data = frame.Data[:dataLen]
|
||||
}
|
||||
|
||||
frame.StreamID = protocol.StreamID(streamID)
|
||||
frame.Offset = protocol.ByteCount(offset)
|
||||
frame.Fin = fin
|
||||
frame.DataLenPresent = hasDataLen
|
||||
|
||||
if dataLen != 0 {
|
||||
if _, err := io.ReadFull(r, frame.Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if frame.Offset+frame.DataLen() > protocol.MaxByteCount {
|
||||
return nil, errors.New("stream data overflows maximum offset")
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// Write writes a STREAM frame
|
||||
func (f *StreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
|
||||
if len(f.Data) == 0 && !f.Fin {
|
||||
return errors.New("StreamFrame: attempting to write empty frame without FIN")
|
||||
}
|
||||
|
||||
typeByte := byte(0x8)
|
||||
if f.Fin {
|
||||
typeByte ^= 0x1
|
||||
}
|
||||
hasOffset := f.Offset != 0
|
||||
if f.DataLenPresent {
|
||||
typeByte ^= 0x2
|
||||
}
|
||||
if hasOffset {
|
||||
typeByte ^= 0x4
|
||||
}
|
||||
b.WriteByte(typeByte)
|
||||
quicvarint.Write(b, uint64(f.StreamID))
|
||||
if hasOffset {
|
||||
quicvarint.Write(b, uint64(f.Offset))
|
||||
}
|
||||
if f.DataLenPresent {
|
||||
quicvarint.Write(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 {
|
||||
length := 1 + quicvarint.Len(uint64(f.StreamID))
|
||||
if f.Offset != 0 {
|
||||
length += quicvarint.Len(uint64(f.Offset))
|
||||
}
|
||||
if f.DataLenPresent {
|
||||
length += quicvarint.Len(uint64(f.DataLen()))
|
||||
}
|
||||
return length + f.DataLen()
|
||||
}
|
||||
|
||||
// DataLen gives the length of data in bytes
|
||||
func (f *StreamFrame) DataLen() protocol.ByteCount {
|
||||
return protocol.ByteCount(len(f.Data))
|
||||
}
|
||||
|
||||
// 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 {
|
||||
headerLen := 1 + quicvarint.Len(uint64(f.StreamID))
|
||||
if f.Offset != 0 {
|
||||
headerLen += quicvarint.Len(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 && quicvarint.Len(uint64(maxDataLen)) != 1 {
|
||||
maxDataLen--
|
||||
}
|
||||
return maxDataLen
|
||||
}
|
||||
|
||||
// MaybeSplitOffFrame splits a frame such that it is not bigger than n bytes.
|
||||
// It returns if the frame was actually split.
|
||||
// The frame might not be split if:
|
||||
// * the size is large enough to fit the whole frame
|
||||
// * the size is too small to fit even a 1-byte frame. In that case, the frame returned is nil.
|
||||
func (f *StreamFrame) MaybeSplitOffFrame(maxSize protocol.ByteCount, version protocol.VersionNumber) (*StreamFrame, bool /* was splitting required */) {
|
||||
if maxSize >= f.Length(version) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
n := f.MaxDataLen(maxSize, version)
|
||||
if n == 0 {
|
||||
return nil, true
|
||||
}
|
||||
|
||||
new := GetStreamFrame()
|
||||
new.StreamID = f.StreamID
|
||||
new.Offset = f.Offset
|
||||
new.Fin = false
|
||||
new.DataLenPresent = f.DataLenPresent
|
||||
|
||||
// swap the data slices
|
||||
new.Data, f.Data = f.Data, new.Data
|
||||
new.fromPool, f.fromPool = f.fromPool, new.fromPool
|
||||
|
||||
f.Data = f.Data[:protocol.ByteCount(len(new.Data))-n]
|
||||
copy(f.Data, new.Data[n:])
|
||||
new.Data = new.Data[:n]
|
||||
f.Offset += n
|
||||
|
||||
return new, true
|
||||
}
|
||||
|
||||
func (f *StreamFrame) PutBack() {
|
||||
putStreamFrame(f)
|
||||
}
|
55
vendor/github.com/lucas-clemente/quic-go/internal/wire/streams_blocked_frame.go
generated
vendored
Normal file
55
vendor/github.com/lucas-clemente/quic-go/internal/wire/streams_blocked_frame.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// A StreamsBlockedFrame is a STREAMS_BLOCKED frame
|
||||
type StreamsBlockedFrame struct {
|
||||
Type protocol.StreamType
|
||||
StreamLimit protocol.StreamNum
|
||||
}
|
||||
|
||||
func parseStreamsBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamsBlockedFrame, error) {
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := &StreamsBlockedFrame{}
|
||||
switch typeByte {
|
||||
case 0x16:
|
||||
f.Type = protocol.StreamTypeBidi
|
||||
case 0x17:
|
||||
f.Type = protocol.StreamTypeUni
|
||||
}
|
||||
streamLimit, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.StreamLimit = protocol.StreamNum(streamLimit)
|
||||
if f.StreamLimit > protocol.MaxStreamCount {
|
||||
return nil, fmt.Errorf("%d exceeds the maximum stream count", f.StreamLimit)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (f *StreamsBlockedFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
||||
switch f.Type {
|
||||
case protocol.StreamTypeBidi:
|
||||
b.WriteByte(0x16)
|
||||
case protocol.StreamTypeUni:
|
||||
b.WriteByte(0x17)
|
||||
}
|
||||
quicvarint.Write(b, uint64(f.StreamLimit))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *StreamsBlockedFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||
return 1 + quicvarint.Len(uint64(f.StreamLimit))
|
||||
}
|
476
vendor/github.com/lucas-clemente/quic-go/internal/wire/transport_parameters.go
generated
vendored
Normal file
476
vendor/github.com/lucas-clemente/quic-go/internal/wire/transport_parameters.go
generated
vendored
Normal file
@@ -0,0 +1,476 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/qerr"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
const transportParameterMarshalingVersion = 1
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
}
|
||||
|
||||
type transportParameterID uint64
|
||||
|
||||
const (
|
||||
originalDestinationConnectionIDParameterID transportParameterID = 0x0
|
||||
maxIdleTimeoutParameterID transportParameterID = 0x1
|
||||
statelessResetTokenParameterID transportParameterID = 0x2
|
||||
maxUDPPayloadSizeParameterID transportParameterID = 0x3
|
||||
initialMaxDataParameterID transportParameterID = 0x4
|
||||
initialMaxStreamDataBidiLocalParameterID transportParameterID = 0x5
|
||||
initialMaxStreamDataBidiRemoteParameterID transportParameterID = 0x6
|
||||
initialMaxStreamDataUniParameterID transportParameterID = 0x7
|
||||
initialMaxStreamsBidiParameterID transportParameterID = 0x8
|
||||
initialMaxStreamsUniParameterID transportParameterID = 0x9
|
||||
ackDelayExponentParameterID transportParameterID = 0xa
|
||||
maxAckDelayParameterID transportParameterID = 0xb
|
||||
disableActiveMigrationParameterID transportParameterID = 0xc
|
||||
preferredAddressParameterID transportParameterID = 0xd
|
||||
activeConnectionIDLimitParameterID transportParameterID = 0xe
|
||||
initialSourceConnectionIDParameterID transportParameterID = 0xf
|
||||
retrySourceConnectionIDParameterID transportParameterID = 0x10
|
||||
// https://datatracker.ietf.org/doc/draft-ietf-quic-datagram/
|
||||
maxDatagramFrameSizeParameterID transportParameterID = 0x20
|
||||
)
|
||||
|
||||
// PreferredAddress is the value encoding in the preferred_address transport parameter
|
||||
type PreferredAddress struct {
|
||||
IPv4 net.IP
|
||||
IPv4Port uint16
|
||||
IPv6 net.IP
|
||||
IPv6Port uint16
|
||||
ConnectionID protocol.ConnectionID
|
||||
StatelessResetToken protocol.StatelessResetToken
|
||||
}
|
||||
|
||||
// TransportParameters are parameters sent to the peer during the handshake
|
||||
type TransportParameters struct {
|
||||
InitialMaxStreamDataBidiLocal protocol.ByteCount
|
||||
InitialMaxStreamDataBidiRemote protocol.ByteCount
|
||||
InitialMaxStreamDataUni protocol.ByteCount
|
||||
InitialMaxData protocol.ByteCount
|
||||
|
||||
MaxAckDelay time.Duration
|
||||
AckDelayExponent uint8
|
||||
|
||||
DisableActiveMigration bool
|
||||
|
||||
MaxUDPPayloadSize protocol.ByteCount
|
||||
|
||||
MaxUniStreamNum protocol.StreamNum
|
||||
MaxBidiStreamNum protocol.StreamNum
|
||||
|
||||
MaxIdleTimeout time.Duration
|
||||
|
||||
PreferredAddress *PreferredAddress
|
||||
|
||||
OriginalDestinationConnectionID protocol.ConnectionID
|
||||
InitialSourceConnectionID protocol.ConnectionID
|
||||
RetrySourceConnectionID *protocol.ConnectionID // use a pointer here to distinguish zero-length connection IDs from missing transport parameters
|
||||
|
||||
StatelessResetToken *protocol.StatelessResetToken
|
||||
ActiveConnectionIDLimit uint64
|
||||
|
||||
MaxDatagramFrameSize protocol.ByteCount
|
||||
}
|
||||
|
||||
// Unmarshal the transport parameters
|
||||
func (p *TransportParameters) Unmarshal(data []byte, sentBy protocol.Perspective) error {
|
||||
if err := p.unmarshal(bytes.NewReader(data), sentBy, false); err != nil {
|
||||
return &qerr.TransportError{
|
||||
ErrorCode: qerr.TransportParameterError,
|
||||
ErrorMessage: err.Error(),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *TransportParameters) unmarshal(r *bytes.Reader, sentBy protocol.Perspective, fromSessionTicket bool) error {
|
||||
// needed to check that every parameter is only sent at most once
|
||||
var parameterIDs []transportParameterID
|
||||
|
||||
var (
|
||||
readOriginalDestinationConnectionID bool
|
||||
readInitialSourceConnectionID bool
|
||||
)
|
||||
|
||||
p.AckDelayExponent = protocol.DefaultAckDelayExponent
|
||||
p.MaxAckDelay = protocol.DefaultMaxAckDelay
|
||||
p.MaxDatagramFrameSize = protocol.InvalidByteCount
|
||||
|
||||
for r.Len() > 0 {
|
||||
paramIDInt, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
paramID := transportParameterID(paramIDInt)
|
||||
paramLen, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if uint64(r.Len()) < paramLen {
|
||||
return fmt.Errorf("remaining length (%d) smaller than parameter length (%d)", r.Len(), paramLen)
|
||||
}
|
||||
parameterIDs = append(parameterIDs, paramID)
|
||||
switch paramID {
|
||||
case maxIdleTimeoutParameterID,
|
||||
maxUDPPayloadSizeParameterID,
|
||||
initialMaxDataParameterID,
|
||||
initialMaxStreamDataBidiLocalParameterID,
|
||||
initialMaxStreamDataBidiRemoteParameterID,
|
||||
initialMaxStreamDataUniParameterID,
|
||||
initialMaxStreamsBidiParameterID,
|
||||
initialMaxStreamsUniParameterID,
|
||||
maxAckDelayParameterID,
|
||||
activeConnectionIDLimitParameterID,
|
||||
maxDatagramFrameSizeParameterID,
|
||||
ackDelayExponentParameterID:
|
||||
if err := p.readNumericTransportParameter(r, paramID, int(paramLen)); err != nil {
|
||||
return err
|
||||
}
|
||||
case preferredAddressParameterID:
|
||||
if sentBy == protocol.PerspectiveClient {
|
||||
return errors.New("client sent a preferred_address")
|
||||
}
|
||||
if err := p.readPreferredAddress(r, int(paramLen)); err != nil {
|
||||
return err
|
||||
}
|
||||
case disableActiveMigrationParameterID:
|
||||
if paramLen != 0 {
|
||||
return fmt.Errorf("wrong length for disable_active_migration: %d (expected empty)", paramLen)
|
||||
}
|
||||
p.DisableActiveMigration = true
|
||||
case statelessResetTokenParameterID:
|
||||
if sentBy == protocol.PerspectiveClient {
|
||||
return errors.New("client sent a stateless_reset_token")
|
||||
}
|
||||
if paramLen != 16 {
|
||||
return fmt.Errorf("wrong length for stateless_reset_token: %d (expected 16)", paramLen)
|
||||
}
|
||||
var token protocol.StatelessResetToken
|
||||
r.Read(token[:])
|
||||
p.StatelessResetToken = &token
|
||||
case originalDestinationConnectionIDParameterID:
|
||||
if sentBy == protocol.PerspectiveClient {
|
||||
return errors.New("client sent an original_destination_connection_id")
|
||||
}
|
||||
p.OriginalDestinationConnectionID, _ = protocol.ReadConnectionID(r, int(paramLen))
|
||||
readOriginalDestinationConnectionID = true
|
||||
case initialSourceConnectionIDParameterID:
|
||||
p.InitialSourceConnectionID, _ = protocol.ReadConnectionID(r, int(paramLen))
|
||||
readInitialSourceConnectionID = true
|
||||
case retrySourceConnectionIDParameterID:
|
||||
if sentBy == protocol.PerspectiveClient {
|
||||
return errors.New("client sent a retry_source_connection_id")
|
||||
}
|
||||
connID, _ := protocol.ReadConnectionID(r, int(paramLen))
|
||||
p.RetrySourceConnectionID = &connID
|
||||
default:
|
||||
r.Seek(int64(paramLen), io.SeekCurrent)
|
||||
}
|
||||
}
|
||||
|
||||
if !fromSessionTicket {
|
||||
if sentBy == protocol.PerspectiveServer && !readOriginalDestinationConnectionID {
|
||||
return errors.New("missing original_destination_connection_id")
|
||||
}
|
||||
if p.MaxUDPPayloadSize == 0 {
|
||||
p.MaxUDPPayloadSize = protocol.MaxByteCount
|
||||
}
|
||||
if !readInitialSourceConnectionID {
|
||||
return errors.New("missing initial_source_connection_id")
|
||||
}
|
||||
}
|
||||
|
||||
// check that every transport parameter was sent at most once
|
||||
sort.Slice(parameterIDs, func(i, j int) bool { return parameterIDs[i] < parameterIDs[j] })
|
||||
for i := 0; i < len(parameterIDs)-1; i++ {
|
||||
if parameterIDs[i] == parameterIDs[i+1] {
|
||||
return fmt.Errorf("received duplicate transport parameter %#x", parameterIDs[i])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *TransportParameters) readPreferredAddress(r *bytes.Reader, expectedLen int) error {
|
||||
remainingLen := r.Len()
|
||||
pa := &PreferredAddress{}
|
||||
ipv4 := make([]byte, 4)
|
||||
if _, err := io.ReadFull(r, ipv4); err != nil {
|
||||
return err
|
||||
}
|
||||
pa.IPv4 = net.IP(ipv4)
|
||||
port, err := utils.BigEndian.ReadUint16(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pa.IPv4Port = port
|
||||
ipv6 := make([]byte, 16)
|
||||
if _, err := io.ReadFull(r, ipv6); err != nil {
|
||||
return err
|
||||
}
|
||||
pa.IPv6 = net.IP(ipv6)
|
||||
port, err = utils.BigEndian.ReadUint16(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pa.IPv6Port = port
|
||||
connIDLen, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if connIDLen == 0 || connIDLen > protocol.MaxConnIDLen {
|
||||
return fmt.Errorf("invalid connection ID length: %d", connIDLen)
|
||||
}
|
||||
connID, err := protocol.ReadConnectionID(r, int(connIDLen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pa.ConnectionID = connID
|
||||
if _, err := io.ReadFull(r, pa.StatelessResetToken[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if bytesRead := remainingLen - r.Len(); bytesRead != expectedLen {
|
||||
return fmt.Errorf("expected preferred_address to be %d long, read %d bytes", expectedLen, bytesRead)
|
||||
}
|
||||
p.PreferredAddress = pa
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *TransportParameters) readNumericTransportParameter(
|
||||
r *bytes.Reader,
|
||||
paramID transportParameterID,
|
||||
expectedLen int,
|
||||
) error {
|
||||
remainingLen := r.Len()
|
||||
val, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while reading transport parameter %d: %s", paramID, err)
|
||||
}
|
||||
if remainingLen-r.Len() != expectedLen {
|
||||
return fmt.Errorf("inconsistent transport parameter length for transport parameter %#x", paramID)
|
||||
}
|
||||
//nolint:exhaustive // This only covers the numeric transport parameters.
|
||||
switch paramID {
|
||||
case initialMaxStreamDataBidiLocalParameterID:
|
||||
p.InitialMaxStreamDataBidiLocal = protocol.ByteCount(val)
|
||||
case initialMaxStreamDataBidiRemoteParameterID:
|
||||
p.InitialMaxStreamDataBidiRemote = protocol.ByteCount(val)
|
||||
case initialMaxStreamDataUniParameterID:
|
||||
p.InitialMaxStreamDataUni = protocol.ByteCount(val)
|
||||
case initialMaxDataParameterID:
|
||||
p.InitialMaxData = protocol.ByteCount(val)
|
||||
case initialMaxStreamsBidiParameterID:
|
||||
p.MaxBidiStreamNum = protocol.StreamNum(val)
|
||||
if p.MaxBidiStreamNum > protocol.MaxStreamCount {
|
||||
return fmt.Errorf("initial_max_streams_bidi too large: %d (maximum %d)", p.MaxBidiStreamNum, protocol.MaxStreamCount)
|
||||
}
|
||||
case initialMaxStreamsUniParameterID:
|
||||
p.MaxUniStreamNum = protocol.StreamNum(val)
|
||||
if p.MaxUniStreamNum > protocol.MaxStreamCount {
|
||||
return fmt.Errorf("initial_max_streams_uni too large: %d (maximum %d)", p.MaxUniStreamNum, protocol.MaxStreamCount)
|
||||
}
|
||||
case maxIdleTimeoutParameterID:
|
||||
p.MaxIdleTimeout = utils.MaxDuration(protocol.MinRemoteIdleTimeout, time.Duration(val)*time.Millisecond)
|
||||
case maxUDPPayloadSizeParameterID:
|
||||
if val < 1200 {
|
||||
return fmt.Errorf("invalid value for max_packet_size: %d (minimum 1200)", val)
|
||||
}
|
||||
p.MaxUDPPayloadSize = protocol.ByteCount(val)
|
||||
case ackDelayExponentParameterID:
|
||||
if val > protocol.MaxAckDelayExponent {
|
||||
return fmt.Errorf("invalid value for ack_delay_exponent: %d (maximum %d)", val, protocol.MaxAckDelayExponent)
|
||||
}
|
||||
p.AckDelayExponent = uint8(val)
|
||||
case maxAckDelayParameterID:
|
||||
if val > uint64(protocol.MaxMaxAckDelay/time.Millisecond) {
|
||||
return fmt.Errorf("invalid value for max_ack_delay: %dms (maximum %dms)", val, protocol.MaxMaxAckDelay/time.Millisecond)
|
||||
}
|
||||
p.MaxAckDelay = time.Duration(val) * time.Millisecond
|
||||
case activeConnectionIDLimitParameterID:
|
||||
p.ActiveConnectionIDLimit = val
|
||||
case maxDatagramFrameSizeParameterID:
|
||||
p.MaxDatagramFrameSize = protocol.ByteCount(val)
|
||||
default:
|
||||
return fmt.Errorf("TransportParameter BUG: transport parameter %d not found", paramID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal the transport parameters
|
||||
func (p *TransportParameters) Marshal(pers protocol.Perspective) []byte {
|
||||
b := &bytes.Buffer{}
|
||||
|
||||
// add a greased value
|
||||
quicvarint.Write(b, uint64(27+31*rand.Intn(100)))
|
||||
length := rand.Intn(16)
|
||||
randomData := make([]byte, length)
|
||||
rand.Read(randomData)
|
||||
quicvarint.Write(b, uint64(length))
|
||||
b.Write(randomData)
|
||||
|
||||
// initial_max_stream_data_bidi_local
|
||||
p.marshalVarintParam(b, initialMaxStreamDataBidiLocalParameterID, uint64(p.InitialMaxStreamDataBidiLocal))
|
||||
// initial_max_stream_data_bidi_remote
|
||||
p.marshalVarintParam(b, initialMaxStreamDataBidiRemoteParameterID, uint64(p.InitialMaxStreamDataBidiRemote))
|
||||
// initial_max_stream_data_uni
|
||||
p.marshalVarintParam(b, initialMaxStreamDataUniParameterID, uint64(p.InitialMaxStreamDataUni))
|
||||
// initial_max_data
|
||||
p.marshalVarintParam(b, initialMaxDataParameterID, uint64(p.InitialMaxData))
|
||||
// initial_max_bidi_streams
|
||||
p.marshalVarintParam(b, initialMaxStreamsBidiParameterID, uint64(p.MaxBidiStreamNum))
|
||||
// initial_max_uni_streams
|
||||
p.marshalVarintParam(b, initialMaxStreamsUniParameterID, uint64(p.MaxUniStreamNum))
|
||||
// idle_timeout
|
||||
p.marshalVarintParam(b, maxIdleTimeoutParameterID, uint64(p.MaxIdleTimeout/time.Millisecond))
|
||||
// max_packet_size
|
||||
p.marshalVarintParam(b, maxUDPPayloadSizeParameterID, uint64(protocol.MaxPacketBufferSize))
|
||||
// max_ack_delay
|
||||
// Only send it if is different from the default value.
|
||||
if p.MaxAckDelay != protocol.DefaultMaxAckDelay {
|
||||
p.marshalVarintParam(b, maxAckDelayParameterID, uint64(p.MaxAckDelay/time.Millisecond))
|
||||
}
|
||||
// ack_delay_exponent
|
||||
// Only send it if is different from the default value.
|
||||
if p.AckDelayExponent != protocol.DefaultAckDelayExponent {
|
||||
p.marshalVarintParam(b, ackDelayExponentParameterID, uint64(p.AckDelayExponent))
|
||||
}
|
||||
// disable_active_migration
|
||||
if p.DisableActiveMigration {
|
||||
quicvarint.Write(b, uint64(disableActiveMigrationParameterID))
|
||||
quicvarint.Write(b, 0)
|
||||
}
|
||||
if pers == protocol.PerspectiveServer {
|
||||
// stateless_reset_token
|
||||
if p.StatelessResetToken != nil {
|
||||
quicvarint.Write(b, uint64(statelessResetTokenParameterID))
|
||||
quicvarint.Write(b, 16)
|
||||
b.Write(p.StatelessResetToken[:])
|
||||
}
|
||||
// original_destination_connection_id
|
||||
quicvarint.Write(b, uint64(originalDestinationConnectionIDParameterID))
|
||||
quicvarint.Write(b, uint64(p.OriginalDestinationConnectionID.Len()))
|
||||
b.Write(p.OriginalDestinationConnectionID.Bytes())
|
||||
// preferred_address
|
||||
if p.PreferredAddress != nil {
|
||||
quicvarint.Write(b, uint64(preferredAddressParameterID))
|
||||
quicvarint.Write(b, 4+2+16+2+1+uint64(p.PreferredAddress.ConnectionID.Len())+16)
|
||||
ipv4 := p.PreferredAddress.IPv4
|
||||
b.Write(ipv4[len(ipv4)-4:])
|
||||
utils.BigEndian.WriteUint16(b, p.PreferredAddress.IPv4Port)
|
||||
b.Write(p.PreferredAddress.IPv6)
|
||||
utils.BigEndian.WriteUint16(b, p.PreferredAddress.IPv6Port)
|
||||
b.WriteByte(uint8(p.PreferredAddress.ConnectionID.Len()))
|
||||
b.Write(p.PreferredAddress.ConnectionID.Bytes())
|
||||
b.Write(p.PreferredAddress.StatelessResetToken[:])
|
||||
}
|
||||
}
|
||||
// active_connection_id_limit
|
||||
p.marshalVarintParam(b, activeConnectionIDLimitParameterID, p.ActiveConnectionIDLimit)
|
||||
// initial_source_connection_id
|
||||
quicvarint.Write(b, uint64(initialSourceConnectionIDParameterID))
|
||||
quicvarint.Write(b, uint64(p.InitialSourceConnectionID.Len()))
|
||||
b.Write(p.InitialSourceConnectionID.Bytes())
|
||||
// retry_source_connection_id
|
||||
if pers == protocol.PerspectiveServer && p.RetrySourceConnectionID != nil {
|
||||
quicvarint.Write(b, uint64(retrySourceConnectionIDParameterID))
|
||||
quicvarint.Write(b, uint64(p.RetrySourceConnectionID.Len()))
|
||||
b.Write(p.RetrySourceConnectionID.Bytes())
|
||||
}
|
||||
if p.MaxDatagramFrameSize != protocol.InvalidByteCount {
|
||||
p.marshalVarintParam(b, maxDatagramFrameSizeParameterID, uint64(p.MaxDatagramFrameSize))
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (p *TransportParameters) marshalVarintParam(b *bytes.Buffer, id transportParameterID, val uint64) {
|
||||
quicvarint.Write(b, uint64(id))
|
||||
quicvarint.Write(b, uint64(quicvarint.Len(val)))
|
||||
quicvarint.Write(b, val)
|
||||
}
|
||||
|
||||
// MarshalForSessionTicket marshals the transport parameters we save in the session ticket.
|
||||
// When sending a 0-RTT enabled TLS session tickets, we need to save the transport parameters.
|
||||
// The client will remember the transport parameters used in the last session,
|
||||
// and apply those to the 0-RTT data it sends.
|
||||
// Saving the transport parameters in the ticket gives the server the option to reject 0-RTT
|
||||
// if the transport parameters changed.
|
||||
// Since the session ticket is encrypted, the serialization format is defined by the server.
|
||||
// For convenience, we use the same format that we also use for sending the transport parameters.
|
||||
func (p *TransportParameters) MarshalForSessionTicket(b *bytes.Buffer) {
|
||||
quicvarint.Write(b, transportParameterMarshalingVersion)
|
||||
|
||||
// initial_max_stream_data_bidi_local
|
||||
p.marshalVarintParam(b, initialMaxStreamDataBidiLocalParameterID, uint64(p.InitialMaxStreamDataBidiLocal))
|
||||
// initial_max_stream_data_bidi_remote
|
||||
p.marshalVarintParam(b, initialMaxStreamDataBidiRemoteParameterID, uint64(p.InitialMaxStreamDataBidiRemote))
|
||||
// initial_max_stream_data_uni
|
||||
p.marshalVarintParam(b, initialMaxStreamDataUniParameterID, uint64(p.InitialMaxStreamDataUni))
|
||||
// initial_max_data
|
||||
p.marshalVarintParam(b, initialMaxDataParameterID, uint64(p.InitialMaxData))
|
||||
// initial_max_bidi_streams
|
||||
p.marshalVarintParam(b, initialMaxStreamsBidiParameterID, uint64(p.MaxBidiStreamNum))
|
||||
// initial_max_uni_streams
|
||||
p.marshalVarintParam(b, initialMaxStreamsUniParameterID, uint64(p.MaxUniStreamNum))
|
||||
// active_connection_id_limit
|
||||
p.marshalVarintParam(b, activeConnectionIDLimitParameterID, p.ActiveConnectionIDLimit)
|
||||
}
|
||||
|
||||
// UnmarshalFromSessionTicket unmarshals transport parameters from a session ticket.
|
||||
func (p *TransportParameters) UnmarshalFromSessionTicket(r *bytes.Reader) error {
|
||||
version, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if version != transportParameterMarshalingVersion {
|
||||
return fmt.Errorf("unknown transport parameter marshaling version: %d", version)
|
||||
}
|
||||
return p.unmarshal(r, protocol.PerspectiveServer, true)
|
||||
}
|
||||
|
||||
// ValidFor0RTT checks if the transport parameters match those saved in the session ticket.
|
||||
func (p *TransportParameters) ValidFor0RTT(saved *TransportParameters) bool {
|
||||
return p.InitialMaxStreamDataBidiLocal >= saved.InitialMaxStreamDataBidiLocal &&
|
||||
p.InitialMaxStreamDataBidiRemote >= saved.InitialMaxStreamDataBidiRemote &&
|
||||
p.InitialMaxStreamDataUni >= saved.InitialMaxStreamDataUni &&
|
||||
p.InitialMaxData >= saved.InitialMaxData &&
|
||||
p.MaxBidiStreamNum >= saved.MaxBidiStreamNum &&
|
||||
p.MaxUniStreamNum >= saved.MaxUniStreamNum &&
|
||||
p.ActiveConnectionIDLimit == saved.ActiveConnectionIDLimit
|
||||
}
|
||||
|
||||
// String returns a string representation, intended for logging.
|
||||
func (p *TransportParameters) String() string {
|
||||
logString := "&wire.TransportParameters{OriginalDestinationConnectionID: %s, InitialSourceConnectionID: %s, "
|
||||
logParams := []interface{}{p.OriginalDestinationConnectionID, p.InitialSourceConnectionID}
|
||||
if p.RetrySourceConnectionID != nil {
|
||||
logString += "RetrySourceConnectionID: %s, "
|
||||
logParams = append(logParams, p.RetrySourceConnectionID)
|
||||
}
|
||||
logString += "InitialMaxStreamDataBidiLocal: %d, InitialMaxStreamDataBidiRemote: %d, InitialMaxStreamDataUni: %d, InitialMaxData: %d, MaxBidiStreamNum: %d, MaxUniStreamNum: %d, MaxIdleTimeout: %s, AckDelayExponent: %d, MaxAckDelay: %s, ActiveConnectionIDLimit: %d"
|
||||
logParams = append(logParams, []interface{}{p.InitialMaxStreamDataBidiLocal, p.InitialMaxStreamDataBidiRemote, p.InitialMaxStreamDataUni, p.InitialMaxData, p.MaxBidiStreamNum, p.MaxUniStreamNum, p.MaxIdleTimeout, p.AckDelayExponent, p.MaxAckDelay, p.ActiveConnectionIDLimit}...)
|
||||
if p.StatelessResetToken != nil { // the client never sends a stateless reset token
|
||||
logString += ", StatelessResetToken: %#x"
|
||||
logParams = append(logParams, *p.StatelessResetToken)
|
||||
}
|
||||
if p.MaxDatagramFrameSize != protocol.InvalidByteCount {
|
||||
logString += ", MaxDatagramFrameSize: %d"
|
||||
logParams = append(logParams, p.MaxDatagramFrameSize)
|
||||
}
|
||||
logString += "}"
|
||||
return fmt.Sprintf(logString, logParams...)
|
||||
}
|
54
vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go
generated
vendored
Normal file
54
vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// ParseVersionNegotiationPacket parses a Version Negotiation packet.
|
||||
func ParseVersionNegotiationPacket(b *bytes.Reader) (*Header, []protocol.VersionNumber, error) {
|
||||
hdr, err := parseHeader(b, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if b.Len() == 0 {
|
||||
//nolint:stylecheck
|
||||
return nil, nil, errors.New("Version Negotiation packet has empty version list")
|
||||
}
|
||||
if b.Len()%4 != 0 {
|
||||
//nolint:stylecheck
|
||||
return nil, nil, errors.New("Version Negotiation packet has a version list with an invalid length")
|
||||
}
|
||||
versions := make([]protocol.VersionNumber, b.Len()/4)
|
||||
for i := 0; b.Len() > 0; i++ {
|
||||
v, err := utils.BigEndian.ReadUint32(b)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
versions[i] = protocol.VersionNumber(v)
|
||||
}
|
||||
return hdr, versions, nil
|
||||
}
|
||||
|
||||
// ComposeVersionNegotiation composes a Version Negotiation
|
||||
func ComposeVersionNegotiation(destConnID, srcConnID protocol.ConnectionID, versions []protocol.VersionNumber) ([]byte, error) {
|
||||
greasedVersions := protocol.GetGreasedVersions(versions)
|
||||
expectedLen := 1 /* type byte */ + 4 /* version field */ + 1 /* dest connection ID length field */ + destConnID.Len() + 1 /* src connection ID length field */ + 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
|
||||
buf.WriteByte(uint8(destConnID.Len()))
|
||||
buf.Write(destConnID)
|
||||
buf.WriteByte(uint8(srcConnID.Len()))
|
||||
buf.Write(srcConnID)
|
||||
for _, v := range greasedVersions {
|
||||
utils.BigEndian.WriteUint32(buf, uint32(v))
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
Reference in New Issue
Block a user