forked from quic-go/quic-go
implement the IETF draft 10 header changes
This commit is contained in:
@@ -27,14 +27,14 @@ const (
|
||||
type PacketType uint8
|
||||
|
||||
const (
|
||||
// PacketTypeInitial is the packet type of a Initial packet
|
||||
PacketTypeInitial PacketType = 2
|
||||
// PacketTypeInitial is the packet type of an Initial packet
|
||||
PacketTypeInitial PacketType = 0x7f
|
||||
// PacketTypeRetry is the packet type of a Retry packet
|
||||
PacketTypeRetry PacketType = 3
|
||||
// PacketTypeHandshake is the packet type of a Cleartext packet
|
||||
PacketTypeHandshake PacketType = 4
|
||||
PacketTypeRetry PacketType = 0x7e
|
||||
// PacketTypeHandshake is the packet type of a Handshake packet
|
||||
PacketTypeHandshake PacketType = 0x7d
|
||||
// PacketType0RTT is the packet type of a 0-RTT packet
|
||||
PacketType0RTT PacketType = 5
|
||||
PacketType0RTT PacketType = 0x7c
|
||||
)
|
||||
|
||||
func (t PacketType) String() string {
|
||||
|
||||
@@ -50,6 +50,7 @@ func ParseHeaderSentByServer(b *bytes.Reader, version protocol.VersionNumber) (*
|
||||
// the client knows the version that this packet was sent with
|
||||
isPublicHeader = !version.UsesTLS()
|
||||
}
|
||||
|
||||
return parsePacketHeader(b, protocol.PerspectiveServer, isPublicHeader)
|
||||
}
|
||||
|
||||
@@ -61,12 +62,13 @@ func ParseHeaderSentByClient(b *bytes.Reader) (*Header, error) {
|
||||
}
|
||||
_ = 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
|
||||
|
||||
// In an IETF QUIC packet header
|
||||
// * either 0x80 is set (for the Long Header)
|
||||
// * or 0x8 is unset (for the Short Header)
|
||||
// In a gQUIC Public Header
|
||||
// * 0x80 is always unset and
|
||||
// * and 0x8 is always set (this is the Connection ID flag, which the client always sets)
|
||||
isPublicHeader := typeByte&0x88 == 0x8
|
||||
return parsePacketHeader(b, protocol.PerspectiveClient, isPublicHeader)
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ var _ = Describe("Header", func() {
|
||||
Context("parsing", func() {
|
||||
It("parses an IETF draft Short Header, when the QUIC version supports TLS", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
// use a short header, which isn't distinguishable from the gQUIC Public Header when looking at the type byte
|
||||
// use a Short Header, which isn't distinguishable from the gQUIC Public Header when looking at the type byte
|
||||
err := (&Header{
|
||||
IsLongHeader: false,
|
||||
KeyPhase: 1,
|
||||
@@ -53,7 +53,7 @@ var _ = Describe("Header", func() {
|
||||
Expect(hdr.Version).To(Equal(protocol.VersionNumber(0x1234)))
|
||||
})
|
||||
|
||||
It("doens't mistake packets with a Short Header for Version Negotiation Packets", func() {
|
||||
It("doesn't mistake packets with a Short Header for Version Negotiation Packets", func() {
|
||||
// make sure this packet could be mistaken for a Version Negotiation Packet, if we only look at the 0x1 bit
|
||||
buf := &bytes.Buffer{}
|
||||
err := (&Header{
|
||||
@@ -62,7 +62,6 @@ var _ = Describe("Header", func() {
|
||||
PacketNumber: 0x42,
|
||||
}).writeHeader(buf)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(buf.Bytes()[0] & 0x1).To(BeEquivalentTo(0x1))
|
||||
hdr, err := ParseHeaderSentByServer(bytes.NewReader(buf.Bytes()), versionIETFHeader)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(hdr.isPublicHeader).To(BeFalse())
|
||||
|
||||
@@ -2,6 +2,7 @@ package wire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
@@ -71,26 +72,40 @@ func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte
|
||||
}
|
||||
|
||||
func parseShortHeader(b *bytes.Reader, typeByte byte) (*Header, error) {
|
||||
hasConnID := typeByte&0x40 > 0
|
||||
omitConnID := typeByte&0x40 > 0
|
||||
var connID uint64
|
||||
if hasConnID {
|
||||
if !omitConnID {
|
||||
var err error
|
||||
connID, err = utils.BigEndian.ReadUint64(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
pnLen := 1 << ((typeByte & 0x3) - 1)
|
||||
// bit 4 must be set, bit 5 must be unset
|
||||
if typeByte&0x18 != 0x10 {
|
||||
return nil, errors.New("invalid bit 4 and 5")
|
||||
}
|
||||
var pnLen protocol.PacketNumberLen
|
||||
switch typeByte & 0x7 {
|
||||
case 0x0:
|
||||
pnLen = protocol.PacketNumberLen1
|
||||
case 0x1:
|
||||
pnLen = protocol.PacketNumberLen2
|
||||
case 0x2:
|
||||
pnLen = protocol.PacketNumberLen4
|
||||
default:
|
||||
return nil, errors.New("invalid short header type")
|
||||
}
|
||||
pn, err := utils.BigEndian.ReadUintN(b, uint8(pnLen))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Header{
|
||||
KeyPhase: int(typeByte&0x20) >> 5,
|
||||
OmitConnectionID: !hasConnID,
|
||||
OmitConnectionID: omitConnID,
|
||||
ConnectionID: protocol.ConnectionID(connID),
|
||||
PacketNumber: protocol.PacketNumber(pn),
|
||||
PacketNumberLen: protocol.PacketNumberLen(pnLen),
|
||||
PacketNumberLen: pnLen,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -112,17 +127,17 @@ func (h *Header) writeLongHeader(b *bytes.Buffer) error {
|
||||
}
|
||||
|
||||
func (h *Header) writeShortHeader(b *bytes.Buffer) error {
|
||||
typeByte := byte(h.KeyPhase << 5)
|
||||
if !h.OmitConnectionID {
|
||||
typeByte := byte(0x10)
|
||||
typeByte ^= byte(h.KeyPhase << 5)
|
||||
if h.OmitConnectionID {
|
||||
typeByte ^= 0x40
|
||||
}
|
||||
switch h.PacketNumberLen {
|
||||
case protocol.PacketNumberLen1:
|
||||
typeByte ^= 0x1
|
||||
case protocol.PacketNumberLen2:
|
||||
typeByte ^= 0x2
|
||||
typeByte ^= 0x1
|
||||
case protocol.PacketNumberLen4:
|
||||
typeByte ^= 0x3
|
||||
typeByte ^= 0x2
|
||||
default:
|
||||
return fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen)
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
Context("short headers", func() {
|
||||
It("reads a short header with a connection ID", func() {
|
||||
data := []byte{
|
||||
0x40 ^ 0x1, //
|
||||
0x10, // 1 byte packet number
|
||||
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
|
||||
0x42, // packet number
|
||||
}
|
||||
@@ -133,7 +133,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
|
||||
It("reads the Key Phase Bit", func() {
|
||||
data := []byte{
|
||||
0x20 ^ 0x1,
|
||||
0x10 ^ 0x40 ^ 0x20,
|
||||
0x11,
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
@@ -146,7 +146,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
|
||||
It("reads a header with omitted connection ID", func() {
|
||||
data := []byte{
|
||||
0x1,
|
||||
0x10 ^ 0x40,
|
||||
0x21, // packet number
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
@@ -161,7 +161,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
|
||||
It("reads a header with a 2 byte packet number", func() {
|
||||
data := []byte{
|
||||
0x2,
|
||||
0x10 ^ 0x40 ^ 0x1,
|
||||
0x13, 0x37, // packet number
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
@@ -175,7 +175,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
|
||||
It("reads a header with a 4 byte packet number", func() {
|
||||
data := []byte{
|
||||
0x3,
|
||||
0x10 ^ 0x40 ^ 0x2,
|
||||
0xde, 0xad, 0xbe, 0xef, // packet number
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
@@ -189,7 +189,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
|
||||
It("errors on EOF", func() {
|
||||
data := []byte{
|
||||
0x40 ^ 0x3,
|
||||
0x10 ^ 0x2,
|
||||
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
|
||||
0xde, 0xca, 0xfb, 0xad, // packet number
|
||||
}
|
||||
@@ -236,7 +236,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
}).writeHeader(buf)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(buf.Bytes()).To(Equal([]byte{
|
||||
0x40 ^ 0x1,
|
||||
0x10,
|
||||
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
|
||||
0x42, // packet number
|
||||
}))
|
||||
@@ -250,7 +250,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
}).writeHeader(buf)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(buf.Bytes()).To(Equal([]byte{
|
||||
0x1,
|
||||
0x10 ^ 0x40,
|
||||
0x42, // packet number
|
||||
}))
|
||||
})
|
||||
@@ -263,7 +263,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
}).writeHeader(buf)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(buf.Bytes()).To(Equal([]byte{
|
||||
0x2,
|
||||
0x10 ^ 0x40 ^ 0x1,
|
||||
0x13, 0x37, // packet number
|
||||
}))
|
||||
})
|
||||
@@ -276,7 +276,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
}).writeHeader(buf)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(buf.Bytes()).To(Equal([]byte{
|
||||
0x3,
|
||||
0x10 ^ 0x40 ^ 0x2,
|
||||
0xde, 0xca, 0xfb, 0xad, // packet number
|
||||
}))
|
||||
})
|
||||
@@ -299,7 +299,7 @@ var _ = Describe("IETF draft Header", func() {
|
||||
}).writeHeader(buf)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(buf.Bytes()).To(Equal([]byte{
|
||||
0x20 ^ 0x1,
|
||||
0x10 ^ 0x40 ^ 0x20,
|
||||
0x42, // packet number
|
||||
}))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user