fix application bug

This commit is contained in:
Jeff
2019-05-13 11:19:18 +08:00
committed by zryfish
parent 996d6fe4c5
commit 5462f51e65
717 changed files with 87703 additions and 53426 deletions

View File

@@ -2,323 +2,241 @@ package wire
import (
"bytes"
"crypto/rand"
"errors"
"fmt"
"io"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
)
// Header is the header of a QUIC packet.
// It contains fields that are only needed for the gQUIC Public Header and the IETF draft Header.
// 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, _ := decodeConnIDLen(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
}
var errUnsupportedVersion = errors.New("unsupported version")
// The Header is the version independent part of the header
type Header struct {
IsPublicHeader bool
Version protocol.VersionNumber
SrcConnectionID protocol.ConnectionID
DestConnectionID protocol.ConnectionID
Raw []byte
Version protocol.VersionNumber
DestConnectionID protocol.ConnectionID
SrcConnectionID protocol.ConnectionID
OrigDestConnectionID protocol.ConnectionID // only needed in the Retry packet
PacketNumberLen protocol.PacketNumberLen
PacketNumber protocol.PacketNumber
IsVersionNegotiation bool
SupportedVersions []protocol.VersionNumber // Version Number sent in a Version Negotiation Packet by the server
// only needed for the gQUIC Public Header
VersionFlag bool
ResetFlag bool
DiversificationNonce []byte
// only needed for the IETF Header
Type protocol.PacketType
IsLongHeader bool
KeyPhase int
PayloadLen protocol.ByteCount
Token []byte
Type protocol.PacketType
Length protocol.ByteCount
Token []byte
SupportedVersions []protocol.VersionNumber // sent in a Version Negotiation Packet
OrigDestConnectionID protocol.ConnectionID // sent in the Retry packet
typeByte byte
parsedLen protocol.ByteCount // how many bytes were read while parsing this header
}
var errInvalidPacketNumberLen = errors.New("invalid packet number length")
// Write writes the Header.
func (h *Header) Write(b *bytes.Buffer, pers protocol.Perspective, ver protocol.VersionNumber) error {
if !ver.UsesIETFHeaderFormat() {
h.IsPublicHeader = true // save that this is a Public Header, so we can log it correctly later
return h.writePublicHeader(b, pers, ver)
// 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, nil
}
return nil, nil, nil, err
}
// write an IETF QUIC header
if h.IsLongHeader {
return h.writeLongHeader(b, ver)
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 h.writeShortHeader(b, ver)
return hdr, data, rest, nil
}
// TODO: add support for the key phase
func (h *Header) writeLongHeader(b *bytes.Buffer, v protocol.VersionNumber) error {
b.WriteByte(byte(0x80 | h.Type))
utils.BigEndian.WriteUint32(b, uint32(h.Version))
connIDLen, err := encodeConnIDLen(h.DestConnectionID, h.SrcConnectionID)
// 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
}
b.WriteByte(connIDLen)
b.Write(h.DestConnectionID.Bytes())
b.Write(h.SrcConnectionID.Bytes())
h.Version = protocol.VersionNumber(v)
if h.Version != 0 && h.typeByte&0x40 == 0 {
return errors.New("not a QUIC packet")
}
connIDLenByte, err := b.ReadByte()
if err != nil {
return err
}
dcil, scil := decodeConnIDLen(connIDLenByte)
h.DestConnectionID, err = protocol.ReadConnectionID(b, dcil)
if err != nil {
return err
}
h.SrcConnectionID, err = protocol.ReadConnectionID(b, scil)
if err != nil {
return err
}
if h.Version == 0 {
return h.parseVersionNegotiationPacket(b)
}
// 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
}
if h.Type == protocol.PacketTypeInitial && v.UsesTokenInHeader() {
utils.WriteVarInt(b, uint64(len(h.Token)))
b.Write(h.Token)
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 {
odcil, err := encodeSingleConnIDLen(h.OrigDestConnectionID)
odcil := decodeSingleConnIDLen(h.typeByte & 0xf)
h.OrigDestConnectionID, err = protocol.ReadConnectionID(b, odcil)
if err != nil {
return err
}
// randomize the first 4 bits
odcilByte := make([]byte, 1)
_, _ = rand.Read(odcilByte) // it's safe to ignore the error here
odcilByte[0] = (odcilByte[0] & 0xf0) | odcil
b.Write(odcilByte)
b.Write(h.OrigDestConnectionID.Bytes())
b.Write(h.Token)
h.Token = make([]byte, b.Len())
if _, err := io.ReadFull(b, h.Token); err != nil {
return err
}
return nil
}
if v.UsesLengthInHeader() {
utils.WriteVarInt(b, uint64(h.PayloadLen))
}
if v.UsesVarintPacketNumbers() {
return utils.WriteVarIntPacketNumber(b, h.PacketNumber, h.PacketNumberLen)
}
utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
if h.Type == protocol.PacketType0RTT && v == protocol.Version44 {
if len(h.DiversificationNonce) != 32 {
return errors.New("invalid diversification nonce length")
if h.Type == protocol.PacketTypeInitial {
tokenLen, err := utils.ReadVarInt(b)
if err != nil {
return err
}
b.Write(h.DiversificationNonce)
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 := utils.ReadVarInt(b)
if err != nil {
return err
}
h.Length = protocol.ByteCount(pl)
return nil
}
func (h *Header) parseVersionNegotiationPacket(b *bytes.Reader) error {
if b.Len() == 0 {
return errors.New("Version Negoation packet has empty version list")
}
if b.Len()%4 != 0 {
return errors.New("Version Negotation packet has a version list with an invalid length")
}
h.SupportedVersions = make([]protocol.VersionNumber, b.Len()/4)
for i := 0; b.Len() > 0; i++ {
v, err := utils.BigEndian.ReadUint32(b)
if err != nil {
return err
}
h.SupportedVersions[i] = protocol.VersionNumber(v)
}
return nil
}
func (h *Header) writeShortHeader(b *bytes.Buffer, v protocol.VersionNumber) error {
typeByte := byte(0x30)
typeByte |= byte(h.KeyPhase << 6)
if !v.UsesVarintPacketNumbers() {
switch h.PacketNumberLen {
case protocol.PacketNumberLen1:
case protocol.PacketNumberLen2:
typeByte |= 0x1
case protocol.PacketNumberLen4:
typeByte |= 0x2
default:
return errInvalidPacketNumberLen
}
}
b.WriteByte(typeByte)
b.Write(h.DestConnectionID.Bytes())
if !v.UsesVarintPacketNumbers() {
switch h.PacketNumberLen {
case protocol.PacketNumberLen1:
b.WriteByte(uint8(h.PacketNumber))
case protocol.PacketNumberLen2:
utils.BigEndian.WriteUint16(b, uint16(h.PacketNumber))
case protocol.PacketNumberLen4:
utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
}
return nil
}
return utils.WriteVarIntPacketNumber(b, h.PacketNumber, h.PacketNumberLen)
// ParsedLen returns the number of bytes that were consumed when parsing the header
func (h *Header) ParsedLen() protocol.ByteCount {
return h.parsedLen
}
// writePublicHeader writes a Public Header.
func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _ protocol.VersionNumber) error {
if h.ResetFlag || (h.VersionFlag && pers == protocol.PerspectiveServer) {
return errors.New("PublicHeader: Can only write regular packets")
}
if h.SrcConnectionID.Len() != 0 {
return errors.New("PublicHeader: SrcConnectionID must not be set")
}
if len(h.DestConnectionID) != 0 && len(h.DestConnectionID) != 8 {
return fmt.Errorf("PublicHeader: wrong length for Connection ID: %d (expected 8)", len(h.DestConnectionID))
}
publicFlagByte := uint8(0x00)
if h.VersionFlag {
publicFlagByte |= 0x01
}
if h.DestConnectionID.Len() > 0 {
publicFlagByte |= 0x08
}
if len(h.DiversificationNonce) > 0 {
if len(h.DiversificationNonce) != 32 {
return errors.New("invalid diversification nonce length")
}
publicFlagByte |= 0x04
}
switch h.PacketNumberLen {
case protocol.PacketNumberLen1:
publicFlagByte |= 0x00
case protocol.PacketNumberLen2:
publicFlagByte |= 0x10
case protocol.PacketNumberLen4:
publicFlagByte |= 0x20
}
b.WriteByte(publicFlagByte)
if h.DestConnectionID.Len() > 0 {
b.Write(h.DestConnectionID)
}
if h.VersionFlag && pers == protocol.PerspectiveClient {
utils.BigEndian.WriteUint32(b, uint32(h.Version))
}
if len(h.DiversificationNonce) > 0 {
b.Write(h.DiversificationNonce)
}
switch h.PacketNumberLen {
case protocol.PacketNumberLen1:
b.WriteByte(uint8(h.PacketNumber))
case protocol.PacketNumberLen2:
utils.BigEndian.WriteUint16(b, uint16(h.PacketNumber))
case protocol.PacketNumberLen4:
utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
case protocol.PacketNumberLen6:
return errInvalidPacketNumberLen
default:
return errors.New("PublicHeader: PacketNumberLen not set")
}
return nil
// 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) {
return h.toExtendedHeader().parse(b, ver)
}
// GetLength determines the length of the Header.
func (h *Header) GetLength(v protocol.VersionNumber) (protocol.ByteCount, error) {
if !v.UsesIETFHeaderFormat() {
return h.getPublicHeaderLength()
}
return h.getHeaderLength(v)
}
func (h *Header) getHeaderLength(v protocol.VersionNumber) (protocol.ByteCount, error) {
if h.IsLongHeader {
length := 1 /* type byte */ + 4 /* version */ + 1 /* conn id len byte */ + protocol.ByteCount(h.DestConnectionID.Len()+h.SrcConnectionID.Len()) + protocol.ByteCount(h.PacketNumberLen)
if v.UsesLengthInHeader() {
length += utils.VarIntLen(uint64(h.PayloadLen))
}
if h.Type == protocol.PacketTypeInitial && v.UsesTokenInHeader() {
length += utils.VarIntLen(uint64(len(h.Token))) + protocol.ByteCount(len(h.Token))
}
if h.Type == protocol.PacketType0RTT && v == protocol.Version44 {
length += protocol.ByteCount(len(h.DiversificationNonce))
}
return length, nil
}
length := protocol.ByteCount(1 /* type byte */ + h.DestConnectionID.Len())
if h.PacketNumberLen != protocol.PacketNumberLen1 && h.PacketNumberLen != protocol.PacketNumberLen2 && h.PacketNumberLen != protocol.PacketNumberLen4 {
return 0, fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen)
}
length += protocol.ByteCount(h.PacketNumberLen)
return length, nil
}
// getPublicHeaderLength gets the length of the publicHeader in bytes.
// It can only be called for regular packets.
func (h *Header) getPublicHeaderLength() (protocol.ByteCount, error) {
length := protocol.ByteCount(1) // 1 byte for public flags
if h.PacketNumberLen == protocol.PacketNumberLen6 {
return 0, errInvalidPacketNumberLen
}
if h.PacketNumberLen != protocol.PacketNumberLen1 && h.PacketNumberLen != protocol.PacketNumberLen2 && h.PacketNumberLen != protocol.PacketNumberLen4 {
return 0, errPacketNumberLenNotSet
}
length += protocol.ByteCount(h.PacketNumberLen)
length += protocol.ByteCount(h.DestConnectionID.Len())
// Version Number in packets sent by the client
if h.VersionFlag {
length += 4
}
length += protocol.ByteCount(len(h.DiversificationNonce))
return length, nil
}
// Log logs the Header
func (h *Header) Log(logger utils.Logger) {
if h.IsPublicHeader {
h.logPublicHeader(logger)
} else {
h.logHeader(logger)
}
}
func (h *Header) logHeader(logger utils.Logger) {
if h.IsLongHeader {
if h.Version == 0 {
logger.Debugf("\tVersionNegotiationPacket{DestConnectionID: %s, SrcConnectionID: %s, SupportedVersions: %s}", h.DestConnectionID, h.SrcConnectionID, h.SupportedVersions)
} else {
var token string
if h.Type == protocol.PacketTypeInitial || h.Type == protocol.PacketTypeRetry {
if len(h.Token) == 0 {
token = "Token: (empty), "
} else {
token = fmt.Sprintf("Token: %#x, ", h.Token)
}
}
if h.Type == protocol.PacketTypeRetry {
logger.Debugf("\tLong Header{Type: %s, DestConnectionID: %s, SrcConnectionID: %s, %sOrigDestConnectionID: %s, Version: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, token, h.OrigDestConnectionID, h.Version)
return
}
if h.Version == protocol.Version44 {
var divNonce string
if h.Type == protocol.PacketType0RTT {
divNonce = fmt.Sprintf("Diversification Nonce: %#x, ", h.DiversificationNonce)
}
logger.Debugf("\tLong Header{Type: %s, DestConnectionID: %s, SrcConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, %sVersion: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, h.PacketNumber, h.PacketNumberLen, divNonce, h.Version)
return
}
logger.Debugf("\tLong Header{Type: %s, DestConnectionID: %s, SrcConnectionID: %s, %sPacketNumber: %#x, PacketNumberLen: %d, PayloadLen: %d, Version: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, token, h.PacketNumber, h.PacketNumberLen, h.PayloadLen, h.Version)
}
} else {
logger.Debugf("\tShort Header{DestConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, KeyPhase: %d}", h.DestConnectionID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase)
}
}
func (h *Header) logPublicHeader(logger utils.Logger) {
ver := "(unset)"
if h.Version != 0 {
ver = h.Version.String()
}
logger.Debugf("\tPublic Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, Version: %s, DiversificationNonce: %#v}", h.DestConnectionID, h.PacketNumber, h.PacketNumberLen, ver, h.DiversificationNonce)
}
func encodeConnIDLen(dest, src protocol.ConnectionID) (byte, error) {
dcil, err := encodeSingleConnIDLen(dest)
if err != nil {
return 0, err
}
scil, err := encodeSingleConnIDLen(src)
if err != nil {
return 0, err
}
return scil | dcil<<4, nil
}
func encodeSingleConnIDLen(id protocol.ConnectionID) (byte, error) {
len := id.Len()
if len == 0 {
return 0, nil
}
if len < 4 || len > 18 {
return 0, fmt.Errorf("invalid connection ID length: %d bytes", len)
}
return byte(len - 3), nil
func (h *Header) toExtendedHeader() *ExtendedHeader {
return &ExtendedHeader{Header: *h}
}
func decodeConnIDLen(enc byte) (int /*dest conn id len*/, int /*src conn id len*/) {