route/vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go

111 lines
3.4 KiB
Go

package wire
import (
"bytes"
"github.com/lucas-clemente/quic-go/internal/protocol"
)
// Header is the header of a QUIC packet.
// It contains fields that are only needed for the gQUIC Public Header and the IETF draft Header.
type Header struct {
Raw []byte
ConnectionID protocol.ConnectionID
OmitConnectionID bool
PacketNumberLen protocol.PacketNumberLen
PacketNumber protocol.PacketNumber
Version protocol.VersionNumber // VersionNumber sent by the client
IsVersionNegotiation bool
SupportedVersions []protocol.VersionNumber // Version Number sent in a Version Negotiation Packet by the server
// only needed for the gQUIC Public Header
VersionFlag bool
ResetFlag bool
DiversificationNonce []byte
// only needed for the IETF Header
Type protocol.PacketType
IsLongHeader bool
KeyPhase int
// only needed for logging
isPublicHeader bool
}
// ParseHeaderSentByServer parses the header for a packet that was sent by the server.
func ParseHeaderSentByServer(b *bytes.Reader, version protocol.VersionNumber) (*Header, error) {
typeByte, err := b.ReadByte()
if err != nil {
return nil, err
}
_ = b.UnreadByte() // unread the type byte
var isPublicHeader bool
if typeByte&0x80 > 0 { // gQUIC always has 0x80 unset. IETF Long Header or Version Negotiation
isPublicHeader = false
} else if typeByte&0xcf == 0x9 { // gQUIC Version Negotiation Packet
isPublicHeader = true
} else {
// the client knows the version that this packet was sent with
isPublicHeader = !version.UsesTLS()
}
return parsePacketHeader(b, protocol.PerspectiveServer, isPublicHeader)
}
// ParseHeaderSentByClient parses the header for a packet that was sent by the client.
func ParseHeaderSentByClient(b *bytes.Reader) (*Header, error) {
typeByte, err := b.ReadByte()
if err != nil {
return nil, err
}
_ = b.UnreadByte() // unread the type byte
// If this is a gQUIC header 0x80 and 0x40 will be set to 0.
// If this is an IETF QUIC header there are two options:
// * either 0x80 will be 1 (for the Long Header)
// * or 0x40 (the Connection ID Flag) will be 0 (for the Short Header), since we don't the client to omit it
isPublicHeader := typeByte&0xc0 == 0
return parsePacketHeader(b, protocol.PerspectiveClient, isPublicHeader)
}
func parsePacketHeader(b *bytes.Reader, sentBy protocol.Perspective, isPublicHeader bool) (*Header, error) {
// This is a gQUIC Public Header.
if isPublicHeader {
hdr, err := parsePublicHeader(b, sentBy)
if err != nil {
return nil, err
}
hdr.isPublicHeader = true // save that this is a Public Header, so we can log it correctly later
return hdr, nil
}
return parseHeader(b, sentBy)
}
// Write writes the Header.
func (h *Header) Write(b *bytes.Buffer, pers protocol.Perspective, version protocol.VersionNumber) error {
if !version.UsesTLS() {
h.isPublicHeader = true // save that this is a Public Header, so we can log it correctly later
return h.writePublicHeader(b, pers, version)
}
return h.writeHeader(b)
}
// GetLength determines the length of the Header.
func (h *Header) GetLength(pers protocol.Perspective, version protocol.VersionNumber) (protocol.ByteCount, error) {
if !version.UsesTLS() {
return h.getPublicHeaderLength(pers)
}
return h.getHeaderLength()
}
// Log logs the Header
func (h *Header) Log() {
if h.isPublicHeader {
h.logPublicHeader()
} else {
h.logHeader()
}
}