implement the IETF draft 10 header changes

This commit is contained in:
Marten Seemann
2018-02-18 10:57:36 +08:00
parent ba00cb9175
commit b6ca910a52
5 changed files with 52 additions and 36 deletions

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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())

View File

@@ -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)
}

View File

@@ -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
}))
})