implement the new header format

Currently, we're only sending and accepting packets with matching source
and destination connection IDs.
This commit is contained in:
Marten Seemann 2018-04-06 10:03:34 +07:00
parent 1a035a265c
commit 52d31dd7ef
19 changed files with 527 additions and 344 deletions

View file

@ -304,11 +304,16 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
}
hdr.Raw = packet[:len(packet)-r.Len()]
if hdr.IsLongHeader && !hdr.DestConnectionID.Equal(hdr.SrcConnectionID) {
c.logger.Errorf("receiving packets with different destination and source connection IDs not supported")
}
c.mutex.Lock()
defer c.mutex.Unlock()
// reject packets with the wrong connection ID
if !hdr.OmitConnectionID && !hdr.ConnectionID.Equal(c.connectionID) {
// TODO(#1003): add support for server-chosen connection IDs
if !hdr.OmitConnectionID && !hdr.DestConnectionID.Equal(c.connectionID) {
return
}
@ -316,7 +321,7 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
cr := c.conn.RemoteAddr()
// check if the remote address and the connection ID match
// otherwise this might be an attacker trying to inject a PUBLIC_RESET to kill the connection
if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || !hdr.ConnectionID.Equal(c.connectionID) {
if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || !hdr.DestConnectionID.Equal(c.connectionID) {
c.logger.Infof("Received a spoofed Public Reset. Ignoring.")
return
}

View file

@ -34,9 +34,10 @@ var _ = Describe("Client", func() {
acceptClientVersionPacket := func(connID protocol.ConnectionID) []byte {
b := &bytes.Buffer{}
err := (&wire.Header{
ConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: 1,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: 1,
}).Write(b, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(err).ToNot(HaveOccurred())
return b.Bytes()
@ -293,9 +294,10 @@ var _ = Describe("Client", func() {
It("recognizes that a packet without VersionFlag means that the server accepted the suggested version", func() {
ph := wire.Header{
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
ConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
DestConnectionID: connID,
SrcConnectionID: connID,
}
b := &bytes.Buffer{}
err := ph.Write(b, protocol.PerspectiveServer, protocol.VersionWhatever)
@ -460,9 +462,10 @@ var _ = Describe("Client", func() {
connID2 := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7}
Expect(connID).ToNot(Equal(connID2))
(&wire.Header{
ConnectionID: connID2,
PacketNumber: 1,
PacketNumberLen: 1,
DestConnectionID: connID2,
SrcConnectionID: connID2,
PacketNumber: 1,
PacketNumberLen: 1,
}).Write(buf, protocol.PerspectiveServer, protocol.VersionWhatever)
cl.handlePacket(addr, buf.Bytes())
Expect(sess.packetCount).To(BeZero())
@ -589,9 +592,10 @@ var _ = Describe("Client", func() {
Context("handling packets", func() {
It("handles packets", func() {
ph := wire.Header{
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
ConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
DestConnectionID: connID,
SrcConnectionID: connID,
}
b := &bytes.Buffer{}
err := ph.Write(b, protocol.PerspectiveServer, cl.version)

View file

@ -25,7 +25,8 @@ var _ = Describe("QUIC Proxy", func() {
hdr := wire.Header{
PacketNumber: p,
PacketNumberLen: protocol.PacketNumberLen6,
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0, 0, 0x13, 0x37},
DestConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0, 0, 0x13, 0x37},
SrcConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0, 0, 0x13, 0x37},
OmitConnectionID: false,
}
hdr.Write(b, protocol.PerspectiveServer, protocol.VersionWhatever)

View file

@ -10,12 +10,16 @@ import (
// 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
Raw []byte
Version protocol.VersionNumber
DestConnectionID protocol.ConnectionID
SrcConnectionID protocol.ConnectionID
OmitConnectionID bool
PacketNumberLen protocol.PacketNumberLen
PacketNumber protocol.PacketNumber
Version protocol.VersionNumber // VersionNumber sent by the client
PacketNumberLen protocol.PacketNumberLen
PacketNumber protocol.PacketNumber
IsVersionNegotiation bool
SupportedVersions []protocol.VersionNumber // Version Number sent in a Version Negotiation Packet by the server

View file

@ -23,11 +23,12 @@ var _ = Describe("Header", func() {
buf := &bytes.Buffer{}
// use a Short Header, which isn't distinguishable from the gQUIC Public Header when looking at the type byte
err := (&Header{
IsLongHeader: false,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
KeyPhase: 1,
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
IsLongHeader: false,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
KeyPhase: 1,
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
}).writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeaderSentByClient(bytes.NewReader(buf.Bytes()))
@ -40,11 +41,12 @@ var _ = Describe("Header", func() {
It("parses an IETF draft header, when the version is not known, but it has Long Header format", func() {
buf := &bytes.Buffer{}
err := (&Header{
IsLongHeader: true,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
Type: protocol.PacketType0RTT,
PacketNumber: 0x42,
Version: 0x1234,
IsLongHeader: true,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
Type: protocol.PacketType0RTT,
PacketNumber: 0x42,
Version: 0x1234,
}).writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeaderSentByClient(bytes.NewReader(buf.Bytes()))
@ -59,10 +61,11 @@ var _ = Describe("Header", 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{
IsLongHeader: false,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 0x42,
IsLongHeader: false,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 0x42,
}).writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeaderSentByServer(bytes.NewReader(buf.Bytes()), versionIETFHeader)
@ -74,16 +77,18 @@ var _ = Describe("Header", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
buf := &bytes.Buffer{}
err := (&Header{
VersionFlag: true,
Version: versionPublicHeader,
ConnectionID: connID,
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
VersionFlag: true,
Version: versionPublicHeader,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
}).writePublicHeader(buf, protocol.PerspectiveClient, versionPublicHeader)
Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeaderSentByClient(bytes.NewReader(buf.Bytes()))
Expect(err).ToNot(HaveOccurred())
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.DestConnectionID).To(Equal(connID))
Expect(hdr.SrcConnectionID).To(Equal(connID))
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x1337)))
Expect(hdr.Version).To(Equal(versionPublicHeader))
Expect(hdr.isPublicHeader).To(BeTrue())
@ -93,7 +98,8 @@ var _ = Describe("Header", func() {
connID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
buf := &bytes.Buffer{}
err := (&Header{
ConnectionID: connID,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
DiversificationNonce: bytes.Repeat([]byte{'f'}, 32),
@ -101,7 +107,8 @@ var _ = Describe("Header", func() {
Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeaderSentByServer(bytes.NewReader(buf.Bytes()), versionPublicHeader)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.DestConnectionID).To(Equal(connID))
Expect(hdr.SrcConnectionID).To(Equal(connID))
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x1337)))
Expect(hdr.DiversificationNonce).To(HaveLen(32))
Expect(hdr.isPublicHeader).To(BeTrue())
@ -110,11 +117,12 @@ var _ = Describe("Header", func() {
It("errors when parsing the gQUIC header fails", func() {
buf := &bytes.Buffer{}
err := (&Header{
VersionFlag: true,
Version: versionPublicHeader,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
VersionFlag: true,
Version: versionPublicHeader,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
}).writePublicHeader(buf, protocol.PerspectiveClient, versionPublicHeader)
Expect(err).ToNot(HaveOccurred())
_, err = ParseHeaderSentByClient(bytes.NewReader(buf.Bytes()[0:12]))
@ -135,7 +143,8 @@ var _ = Describe("Header", func() {
hdr, err := ParseHeaderSentByServer(bytes.NewReader(data), protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.isPublicHeader).To(BeTrue())
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.DestConnectionID).To(Equal(connID))
Expect(hdr.SrcConnectionID).To(Equal(connID))
// in addition to the versions, the supported versions might contain a reserved version number
for _, version := range versions {
Expect(hdr.SupportedVersions).To(ContainElement(version))
@ -143,14 +152,17 @@ var _ = Describe("Header", func() {
})
It("parses an IETF draft style Version Negotiation Packet", func() {
connID := protocol.ConnectionID{1, 3, 3, 7, 1, 3, 3, 7}
destConnID := protocol.ConnectionID{1, 3, 3, 7, 1, 3, 3, 7}
srcConnID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
versions := []protocol.VersionNumber{0x13, 0x37}
data := ComposeVersionNegotiation(connID, versions)
data, err := ComposeVersionNegotiation(destConnID, srcConnID, versions)
Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeaderSentByServer(bytes.NewReader(data), protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.isPublicHeader).To(BeFalse())
Expect(hdr.IsVersionNegotiation).To(BeTrue())
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.DestConnectionID).To(Equal(destConnID))
Expect(hdr.SrcConnectionID).To(Equal(srcConnID))
Expect(hdr.Version).To(BeZero())
// in addition to the versions, the supported versions might contain a reserved version number
for _, version := range versions {
@ -163,9 +175,10 @@ var _ = Describe("Header", func() {
It("writes a gQUIC Public Header", func() {
buf := &bytes.Buffer{}
hdr := &Header{
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
}
err := hdr.Write(buf, protocol.PerspectiveServer, versionPublicHeader)
Expect(err).ToNot(HaveOccurred())
@ -177,10 +190,11 @@ var _ = Describe("Header", func() {
It("writes a IETF draft header", func() {
buf := &bytes.Buffer{}
hdr := &Header{
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
KeyPhase: 1,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
KeyPhase: 1,
}
err := hdr.Write(buf, protocol.PerspectiveServer, versionIETFHeader)
Expect(err).ToNot(HaveOccurred())
@ -194,7 +208,8 @@ var _ = Describe("Header", func() {
It("get the length of a gQUIC Public Header", func() {
buf := &bytes.Buffer{}
hdr := &Header{
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
DiversificationNonce: bytes.Repeat([]byte{'f'}, 32),
@ -214,11 +229,12 @@ var _ = Describe("Header", func() {
It("get the length of a a IETF draft header", func() {
buf := &bytes.Buffer{}
hdr := &Header{
IsLongHeader: true,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
KeyPhase: 1,
IsLongHeader: true,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
KeyPhase: 1,
}
err := hdr.Write(buf, protocol.PerspectiveServer, versionIETFHeader)
Expect(err).ToNot(HaveOccurred())
@ -252,16 +268,18 @@ var _ = Describe("Header", func() {
It("logs an IETF draft header", func() {
(&Header{
IsLongHeader: true,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
IsLongHeader: true,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
}).Log(logger)
Expect(buf.String()).To(ContainSubstring("Long Header"))
})
It("logs a Public Header", func() {
(&Header{
isPublicHeader: true,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
isPublicHeader: true,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
}).Log(logger)
Expect(buf.String()).To(ContainSubstring("Public Header"))
})

View file

@ -25,21 +25,42 @@ func parseHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Header, e
// parse long header and version negotiation packets
func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte) (*Header, error) {
connID := make(protocol.ConnectionID, 8)
if _, err := io.ReadFull(b, connID); err != nil {
if err == io.ErrUnexpectedEOF {
err = io.EOF
}
return nil, err
}
v, err := utils.BigEndian.ReadUint32(b)
if err != nil {
return nil, err
}
h := &Header{
ConnectionID: connID,
Version: protocol.VersionNumber(v),
connIDLenByte, err := b.ReadByte()
if err != nil {
return nil, err
}
dcil, scil := decodeConnIDLen(connIDLenByte)
var destConnID, srcConnID protocol.ConnectionID
if dcil > 0 {
destConnID = make(protocol.ConnectionID, dcil)
if _, err := io.ReadFull(b, destConnID); err != nil {
if err == io.ErrUnexpectedEOF {
err = io.EOF
}
return nil, err
}
}
if scil > 0 {
srcConnID = make(protocol.ConnectionID, scil)
if _, err := io.ReadFull(b, srcConnID); err != nil {
if err == io.ErrUnexpectedEOF {
err = io.EOF
}
return nil, err
}
}
h := &Header{
Version: protocol.VersionNumber(v),
DestConnectionID: destConnID,
SrcConnectionID: srcConnID,
}
if v == 0 { // version negotiation packet
if sentBy == protocol.PerspectiveClient {
return nil, qerr.InvalidVersion
@ -58,6 +79,7 @@ func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte
}
return h, nil
}
h.IsLongHeader = true
pn, err := utils.BigEndian.ReadUint32(b)
if err != nil {
@ -76,22 +98,19 @@ func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte
}
func parseShortHeader(b *bytes.Reader, typeByte byte) (*Header, error) {
omitConnID := typeByte&0x40 > 0
connID := make(protocol.ConnectionID, 8)
if !omitConnID {
if _, err := io.ReadFull(b, connID); err != nil {
if err == io.ErrUnexpectedEOF {
err = io.EOF
}
return nil, err
if _, err := io.ReadFull(b, connID); err != nil {
if err == io.ErrUnexpectedEOF {
err = io.EOF
}
return nil, err
}
// bit 4 must be set, bit 5 must be unset
if typeByte&0x18 != 0x10 {
return nil, errors.New("invalid bit 4 and 5")
// bits 2 and 3 must be set, bit 4 must be unset
if typeByte&0x38 != 0x30 {
return nil, errors.New("invalid bits 3, 4 and 5")
}
var pnLen protocol.PacketNumberLen
switch typeByte & 0x7 {
switch typeByte & 0x3 {
case 0x0:
pnLen = protocol.PacketNumberLen1
case 0x1:
@ -106,9 +125,8 @@ func parseShortHeader(b *bytes.Reader, typeByte byte) (*Header, error) {
return nil, err
}
return &Header{
KeyPhase: int(typeByte&0x20) >> 5,
OmitConnectionID: omitConnID,
ConnectionID: connID,
KeyPhase: int(typeByte&0x40) >> 6,
DestConnectionID: connID,
PacketNumber: protocol.PacketNumber(pn),
PacketNumberLen: pnLen,
}, nil
@ -124,33 +142,40 @@ func (h *Header) writeHeader(b *bytes.Buffer) error {
// TODO: add support for the key phase
func (h *Header) writeLongHeader(b *bytes.Buffer) error {
if !h.DestConnectionID.Equal(h.SrcConnectionID) {
return errors.New("Header: can't write a header with different source and destination connection ID")
}
if len(h.SrcConnectionID) != 8 {
return fmt.Errorf("Header: source connection ID must be 8 bytes, is %d", len(h.SrcConnectionID))
}
b.WriteByte(byte(0x80 | h.Type))
b.Write(h.ConnectionID)
utils.BigEndian.WriteUint32(b, uint32(h.Version))
connIDLen, err := encodeConnIDLen(h.DestConnectionID, h.SrcConnectionID)
if err != nil {
return err
}
b.WriteByte(connIDLen)
b.Write(h.DestConnectionID)
b.Write(h.SrcConnectionID)
utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
return nil
}
func (h *Header) writeShortHeader(b *bytes.Buffer) error {
typeByte := byte(0x10)
typeByte ^= byte(h.KeyPhase << 5)
if h.OmitConnectionID {
typeByte ^= 0x40
}
typeByte := byte(0x30)
typeByte |= byte(h.KeyPhase << 6)
switch h.PacketNumberLen {
case protocol.PacketNumberLen1:
case protocol.PacketNumberLen2:
typeByte ^= 0x1
typeByte |= 0x1
case protocol.PacketNumberLen4:
typeByte ^= 0x2
typeByte |= 0x2
default:
return fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen)
}
b.WriteByte(typeByte)
if !h.OmitConnectionID {
b.Write(h.ConnectionID)
}
b.Write(h.DestConnectionID)
switch h.PacketNumberLen {
case protocol.PacketNumberLen1:
b.WriteByte(uint8(h.PacketNumber))
@ -165,13 +190,10 @@ func (h *Header) writeShortHeader(b *bytes.Buffer) error {
// getHeaderLength gets the length of the Header in bytes.
func (h *Header) getHeaderLength() (protocol.ByteCount, error) {
if h.IsLongHeader {
return 1 + 8 + 4 + 4, nil
return 1 /* type byte */ + 4 /* version */ + 1 /* conn id len byte */ + protocol.ByteCount(len(h.DestConnectionID)+len(h.SrcConnectionID)) + 4 /* packet number */, nil
}
length := protocol.ByteCount(1) // type byte
if !h.OmitConnectionID {
length += 8
}
length := protocol.ByteCount(1 /* type byte */ + len(h.DestConnectionID))
if h.PacketNumberLen != protocol.PacketNumberLen1 && h.PacketNumberLen != protocol.PacketNumberLen2 && h.PacketNumberLen != protocol.PacketNumberLen4 {
return 0, fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen)
}
@ -181,12 +203,41 @@ func (h *Header) getHeaderLength() (protocol.ByteCount, error) {
func (h *Header) logHeader(logger utils.Logger) {
if h.IsLongHeader {
logger.Debugf(" Long Header{Type: %s, ConnectionID: %#x, PacketNumber: %#x, Version: %s}", h.Type, h.ConnectionID, h.PacketNumber, h.Version)
logger.Debugf(" Long Header{Type: %s, DestConnectionID: %#x, SrcConnectionID: %#x, PacketNumber: %#x, Version: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, h.PacketNumber, h.Version)
} else {
connID := "(omitted)"
if !h.OmitConnectionID {
connID = fmt.Sprintf("%#x", h.ConnectionID)
}
logger.Debugf(" Short Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, KeyPhase: %d}", connID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase)
logger.Debugf(" Short Header{DestConnectionID: %#x, PacketNumber: %#x, PacketNumberLen: %d, KeyPhase: %d}", h.DestConnectionID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase)
}
}
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) {
if len(id) == 0 {
return 0, nil
}
if len(id) < 4 || len(id) > 18 {
return 0, errors.New("invalid connection ID length")
}
return byte(len(id) - 3), nil
}
func decodeConnIDLen(enc byte) (int /*dest conn id len*/, int /*src conn id len*/) {
return decodeSingleConnIDLen(enc >> 4), decodeSingleConnIDLen(enc & 0xf)
}
func decodeSingleConnIDLen(enc uint8) int {
if enc == 0 {
return 0
}
return int(enc) + 3
}

View file

@ -15,19 +15,21 @@ import (
. "github.com/onsi/gomega"
)
var _ = Describe("IETF draft Header", func() {
var _ = Describe("IETF QUIC Header", func() {
Context("parsing", func() {
Context("Version Negotiation Packets", func() {
It("parses", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
versions := []protocol.VersionNumber{0x22334455, 0x33445566}
data := ComposeVersionNegotiation(connID, versions)
data, err := ComposeVersionNegotiation(connID, connID, versions)
Expect(err).ToNot(HaveOccurred())
b := bytes.NewReader(data)
h, err := parseHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(h.IsVersionNegotiation).To(BeTrue())
Expect(h.Version).To(BeZero())
Expect(h.ConnectionID).To(Equal(connID))
Expect(h.DestConnectionID).To(Equal(connID))
Expect(h.SrcConnectionID).To(Equal(connID))
for _, v := range versions {
Expect(h.SupportedVersions).To(ContainElement(v))
}
@ -36,18 +38,20 @@ var _ = Describe("IETF draft Header", func() {
It("errors if it contains versions of the wrong length", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
versions := []protocol.VersionNumber{0x22334455, 0x33445566}
data := ComposeVersionNegotiation(connID, versions)
data, err := ComposeVersionNegotiation(connID, connID, versions)
Expect(err).ToNot(HaveOccurred())
b := bytes.NewReader(data[:len(data)-2])
_, err := parseHeader(b, protocol.PerspectiveServer)
_, err = parseHeader(b, protocol.PerspectiveServer)
Expect(err).To(MatchError(qerr.InvalidVersionNegotiationPacket))
})
It("errors if the version list is empty", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
versions := []protocol.VersionNumber{0x22334455}
data := ComposeVersionNegotiation(connID, versions)
data, err := ComposeVersionNegotiation(connID, connID, versions)
Expect(err).ToNot(HaveOccurred())
// remove 8 bytes (two versions), since ComposeVersionNegotiation also added a reserved version number
_, err := parseHeader(bytes.NewReader(data[:len(data)-8]), protocol.PerspectiveServer)
_, err = parseHeader(bytes.NewReader(data[:len(data)-8]), protocol.PerspectiveServer)
Expect(err).To(MatchError("InvalidVersionNegotiationPacket: empty version list"))
})
})
@ -56,8 +60,10 @@ var _ = Describe("IETF draft Header", func() {
generatePacket := func(t protocol.PacketType) []byte {
return []byte{
0x80 ^ uint8(t),
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0x1, 0x2, 0x3, 0x4, // version number
0x55, // connection ID lengths
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // destination connection ID
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // source connection ID
0xde, 0xca, 0xfb, 0xad, // packet number
}
}
@ -69,7 +75,8 @@ var _ = Describe("IETF draft Header", func() {
Expect(h.Type).To(Equal(protocol.PacketTypeInitial))
Expect(h.IsLongHeader).To(BeTrue())
Expect(h.OmitConnectionID).To(BeFalse())
Expect(h.ConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}))
Expect(h.DestConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}))
Expect(h.SrcConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}))
Expect(h.PacketNumber).To(Equal(protocol.PacketNumber(0xdecafbad)))
Expect(h.PacketNumberLen).To(Equal(protocol.PacketNumberLen4))
Expect(h.Version).To(Equal(protocol.VersionNumber(0x1020304)))
@ -98,8 +105,10 @@ var _ = Describe("IETF draft Header", func() {
It("rejects version 0 for packets sent by the client", func() {
data := []byte{
0x80 ^ uint8(protocol.PacketTypeInitial),
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0x0, 0x0, 0x0, 0x0, // version number
0x55,
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // dest connection ID
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // src connection ID
0xde, 0xca, 0xfb, 0xad, // packet number
}
_, err := parseHeader(bytes.NewReader(data), protocol.PerspectiveClient)
@ -118,7 +127,7 @@ var _ = Describe("IETF draft Header", func() {
Context("short headers", func() {
It("reads a short header with a connection ID", func() {
data := []byte{
0x10, // 1 byte packet number
0x30, // 1 byte packet number
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0x42, // packet number
}
@ -128,7 +137,8 @@ var _ = Describe("IETF draft Header", func() {
Expect(h.IsLongHeader).To(BeFalse())
Expect(h.KeyPhase).To(Equal(0))
Expect(h.OmitConnectionID).To(BeFalse())
Expect(h.ConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}))
Expect(h.DestConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}))
Expect(h.SrcConnectionID).To(BeEmpty())
Expect(h.PacketNumber).To(Equal(protocol.PacketNumber(0x42)))
Expect(h.IsVersionNegotiation).To(BeFalse())
Expect(b.Len()).To(BeZero())
@ -136,7 +146,8 @@ var _ = Describe("IETF draft Header", func() {
It("reads the Key Phase Bit", func() {
data := []byte{
0x10 ^ 0x40 ^ 0x20,
0x30 ^ 0x40,
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0x11,
}
b := bytes.NewReader(data)
@ -147,24 +158,10 @@ var _ = Describe("IETF draft Header", func() {
Expect(b.Len()).To(BeZero())
})
It("reads a header with omitted connection ID", func() {
data := []byte{
0x10 ^ 0x40,
0x21, // packet number
}
b := bytes.NewReader(data)
h, err := parseHeader(b, protocol.PerspectiveClient)
Expect(err).ToNot(HaveOccurred())
Expect(h.IsLongHeader).To(BeFalse())
Expect(h.OmitConnectionID).To(BeTrue())
Expect(h.PacketNumber).To(Equal(protocol.PacketNumber(0x21)))
Expect(h.PacketNumberLen).To(Equal(protocol.PacketNumberLen1))
Expect(b.Len()).To(BeZero())
})
It("reads a header with a 2 byte packet number", func() {
data := []byte{
0x10 ^ 0x40 ^ 0x1,
0x30 ^ 0x40 ^ 0x1,
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0x13, 0x37, // packet number
}
b := bytes.NewReader(data)
@ -178,7 +175,8 @@ var _ = Describe("IETF draft Header", func() {
It("reads a header with a 4 byte packet number", func() {
data := []byte{
0x10 ^ 0x40 ^ 0x2,
0x30 ^ 0x40 ^ 0x2,
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0xde, 0xad, 0xbe, 0xef, // packet number
}
b := bytes.NewReader(data)
@ -190,9 +188,31 @@ var _ = Describe("IETF draft Header", func() {
Expect(b.Len()).To(BeZero())
})
It("rejects headers that have an invalid type", func() {
data := []byte{
0x30 ^ 0x40 ^ 0x3,
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0xde, 0xad, 0xbe, 0xef, // packet number
}
b := bytes.NewReader(data)
_, err := parseHeader(b, protocol.PerspectiveClient)
Expect(err).To(MatchError("invalid short header type"))
})
It("rejects headers that have bit 3,4 and 5 set incorrectly", func() {
data := []byte{
0x38 ^ 0x2,
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0xde, 0xca, 0xfb, 0xad, // packet number
}
b := bytes.NewReader(data)
_, err := parseHeader(b, protocol.PerspectiveClient)
Expect(err).To(MatchError("invalid bits 3, 4 and 5"))
})
It("errors on EOF", func() {
data := []byte{
0x10 ^ 0x2,
0x30 ^ 0x2,
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0xde, 0xca, 0xfb, 0xad, // packet number
}
@ -214,32 +234,44 @@ var _ = Describe("IETF draft Header", func() {
Context("long header", func() {
It("writes", func() {
err := (&Header{
IsLongHeader: true,
Type: 0x5,
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
PacketNumber: 0xdecafbad,
Version: 0x1020304,
IsLongHeader: true,
Type: 0x5,
DestConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
SrcConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
PacketNumber: 0xdecafbad,
Version: 0x1020304,
}).writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
Expect(buf.Bytes()).To(Equal([]byte{
0x80 ^ 0x5,
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0x1, 0x2, 0x3, 0x4, // version number
0x55, // connection ID lengths
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0xde, 0xca, 0xfb, 0xad, // packet number
}))
})
It("refuses to write headers with unequal destination and source connection IDs", func() {
err := (&Header{
IsLongHeader: true,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1},
}).writeHeader(buf)
Expect(err).To(MatchError("Header: can't write a header with different source and destination connection ID"))
})
})
Context("short header", func() {
It("writes a header with connection ID", func() {
err := (&Header{
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 0x42,
DestConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 0x42,
}).writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
Expect(buf.Bytes()).To(Equal([]byte{
0x10,
0x30,
0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID
0x42, // packet number
}))
@ -247,13 +279,12 @@ var _ = Describe("IETF draft Header", func() {
It("writes a header without connection ID", func() {
err := (&Header{
OmitConnectionID: true,
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 0x42,
}).writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
Expect(buf.Bytes()).To(Equal([]byte{
0x10 ^ 0x40,
0x30,
0x42, // packet number
}))
})
@ -266,7 +297,7 @@ var _ = Describe("IETF draft Header", func() {
}).writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
Expect(buf.Bytes()).To(Equal([]byte{
0x10 ^ 0x40 ^ 0x1,
0x30 | 0x1,
0x13, 0x37, // packet number
}))
})
@ -279,7 +310,7 @@ var _ = Describe("IETF draft Header", func() {
}).writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
Expect(buf.Bytes()).To(Equal([]byte{
0x10 ^ 0x40 ^ 0x2,
0x30 | 0x2,
0xde, 0xca, 0xfb, 0xad, // packet number
}))
})
@ -302,7 +333,7 @@ var _ = Describe("IETF draft Header", func() {
}).writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
Expect(buf.Bytes()).To(Equal([]byte{
0x10 ^ 0x40 ^ 0x20,
0x30 | 0x40,
0x42, // packet number
}))
})
@ -318,19 +349,21 @@ var _ = Describe("IETF draft Header", func() {
It("has the right length for the long header", func() {
h := &Header{
IsLongHeader: true,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
IsLongHeader: true,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
}
Expect(h.getHeaderLength()).To(Equal(protocol.ByteCount(17)))
expectedLen := 1 /* type byte */ + 4 /* version */ + 1 /* conn ID len */ + 8 /* dest conn id */ + 8 /* src conn id */ + 4 /* packet number */
Expect(h.getHeaderLength()).To(BeEquivalentTo(expectedLen))
err := h.writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
Expect(buf.Len()).To(Equal(17))
Expect(buf.Len()).To(Equal(expectedLen))
})
It("has the right length for a short header containing a connection ID", func() {
h := &Header{
PacketNumberLen: protocol.PacketNumberLen1,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumberLen: protocol.PacketNumberLen1,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
}
Expect(h.getHeaderLength()).To(Equal(protocol.ByteCount(1 + 8 + 1)))
err := h.writeHeader(buf)
@ -397,33 +430,24 @@ var _ = Describe("IETF draft Header", func() {
It("logs Long Headers", func() {
(&Header{
IsLongHeader: true,
Type: protocol.PacketTypeHandshake,
PacketNumber: 0x1337,
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
Version: 0xfeed,
IsLongHeader: true,
Type: protocol.PacketTypeHandshake,
PacketNumber: 0x1337,
DestConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
SrcConnectionID: protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad, 0x013, 0x37, 0x13, 0x37},
Version: 0xfeed,
}).logHeader(logger)
Expect(buf.String()).To(ContainSubstring("Long Header{Type: Handshake, ConnectionID: 0xdeadbeefcafe1337, PacketNumber: 0x1337, Version: 0xfeed}"))
Expect(buf.String()).To(ContainSubstring("Long Header{Type: Handshake, DestConnectionID: 0xdeadbeefcafe1337, SrcConnectionID: 0xdecafbad13371337, PacketNumber: 0x1337, Version: 0xfeed}"))
})
It("logs Short Headers containing a connection ID", func() {
(&Header{
KeyPhase: 1,
PacketNumber: 0x1337,
PacketNumberLen: 4,
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
KeyPhase: 1,
PacketNumber: 0x1337,
PacketNumberLen: 4,
DestConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
}).logHeader(logger)
Expect(buf.String()).To(ContainSubstring("Short Header{ConnectionID: 0xdeadbeefcafe1337, PacketNumber: 0x1337, PacketNumberLen: 4, KeyPhase: 1}"))
})
It("logs Short Headers with omitted connection ID", func() {
(&Header{
PacketNumber: 0x12,
PacketNumberLen: 1,
OmitConnectionID: true,
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
}).logHeader(logger)
Expect(buf.String()).To(ContainSubstring("Short Header{ConnectionID: (omitted), PacketNumber: 0x12, PacketNumberLen: 1, KeyPhase: 0}"))
Expect(buf.String()).To(ContainSubstring("Short Header{DestConnectionID: 0xdeadbeefcafe1337, PacketNumber: 0x1337, PacketNumberLen: 4, KeyPhase: 1}"))
})
})
})

View file

@ -26,8 +26,11 @@ func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _
if h.VersionFlag && h.ResetFlag {
return errResetAndVersionFlagSet
}
if len(h.ConnectionID) != 8 {
return fmt.Errorf("PublicHeader: wrong length for Connection ID: %d (expected 8)", len(h.ConnectionID))
if !h.DestConnectionID.Equal(h.SrcConnectionID) {
return fmt.Errorf("PublicHeader: SrcConnectionID must be equal to DestConnectionID")
}
if len(h.DestConnectionID) != 8 {
return fmt.Errorf("PublicHeader: wrong length for Connection ID: %d (expected 8)", len(h.DestConnectionID))
}
publicFlagByte := uint8(0x00)
@ -62,7 +65,7 @@ func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _
b.WriteByte(publicFlagByte)
if !h.OmitConnectionID {
b.Write(h.ConnectionID)
b.Write(h.DestConnectionID)
}
if h.VersionFlag && pers == protocol.PerspectiveClient {
utils.BigEndian.WriteUint32(b, uint32(h.Version))
@ -139,8 +142,8 @@ func parsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Hea
if connID[0] == 0 && connID[1] == 0 && connID[2] == 0 && connID[3] == 0 && connID[4] == 0 && connID[5] == 0 && connID[6] == 0 && connID[7] == 0 {
return nil, errInvalidConnectionID
}
header.ConnectionID = connID
header.DestConnectionID = connID
header.SrcConnectionID = connID
}
// Contrary to what the gQUIC wire spec says, the 0x4 bit only indicates the presence of the diversification nonce for packets sent by the server.
@ -240,7 +243,7 @@ func (h *Header) hasPacketNumber(packetSentBy protocol.Perspective) bool {
func (h *Header) logPublicHeader(logger utils.Logger) {
connID := "(omitted)"
if !h.OmitConnectionID {
connID = fmt.Sprintf("%#x", h.ConnectionID)
connID = fmt.Sprintf("%#x", h.DestConnectionID)
}
ver := "(unset)"
if h.Version != 0 {

View file

@ -14,6 +14,8 @@ import (
)
var _ = Describe("Public Header", func() {
connID := protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}
Context("when parsing", func() {
It("accepts a sample client header", func() {
ver := make([]byte, 4)
@ -24,7 +26,9 @@ var _ = Describe("Public Header", func() {
Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.IsVersionNegotiation).To(BeFalse())
Expect(hdr.ResetFlag).To(BeFalse())
Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}))
connID := protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}
Expect(hdr.DestConnectionID).To(Equal(connID))
Expect(hdr.SrcConnectionID).To(Equal(connID))
Expect(hdr.Version).To(Equal(protocol.SupportedVersions[0]))
Expect(hdr.SupportedVersions).To(BeEmpty())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(1)))
@ -37,12 +41,13 @@ var _ = Describe("Public Header", func() {
Expect(err).To(MatchError(errReceivedOmittedConnectionID))
})
It("accepts aan d connection ID as a client", func() {
It("accepts an omitted connection ID as a client", func() {
b := bytes.NewReader([]byte{0x00, 0x01})
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.OmitConnectionID).To(BeTrue())
Expect(hdr.ConnectionID).To(BeEmpty())
Expect(hdr.DestConnectionID).To(BeEmpty())
Expect(hdr.SrcConnectionID).To(BeEmpty())
Expect(b.Len()).To(BeZero())
})
@ -52,14 +57,6 @@ var _ = Describe("Public Header", func() {
Expect(err).To(MatchError(errInvalidConnectionID))
})
It("reads a PUBLIC_RESET packet", func() {
b := bytes.NewReader([]byte{0xa, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8})
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.ResetFlag).To(BeTrue())
Expect(hdr.ConnectionID).ToNot(BeEmpty())
})
It("parses a PUBLIC_RESET packet", func() {
b := bytes.NewReader([]byte{0xa, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8})
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
@ -67,7 +64,9 @@ var _ = Describe("Public Header", func() {
Expect(hdr.ResetFlag).To(BeTrue())
Expect(hdr.VersionFlag).To(BeFalse())
Expect(hdr.IsVersionNegotiation).To(BeFalse())
Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}))
connID := protocol.ConnectionID{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}
Expect(hdr.SrcConnectionID).To(Equal(connID))
Expect(hdr.DestConnectionID).To(Equal(connID))
})
It("reads a diversification nonce sent by the server", func() {
@ -76,7 +75,8 @@ var _ = Describe("Public Header", func() {
b := bytes.NewReader(append(append([]byte{0x0c, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c}, divNonce...), 0x37))
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.ConnectionID).To(Not(BeEmpty()))
Expect(hdr.DestConnectionID).ToNot(BeEmpty())
Expect(hdr.SrcConnectionID).ToNot(BeEmpty())
Expect(hdr.DiversificationNonce).To(Equal(divNonce))
Expect(b.Len()).To(BeZero())
})
@ -94,7 +94,8 @@ var _ = Describe("Public Header", func() {
b := bytes.NewReader(ComposeGQUICVersionNegotiation(connID, versions))
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.DestConnectionID).To(Equal(connID))
Expect(hdr.SrcConnectionID).To(Equal(connID))
Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.Version).To(BeZero()) // unitialized
Expect(hdr.IsVersionNegotiation).To(BeTrue())
@ -177,9 +178,10 @@ var _ = Describe("Public Header", func() {
It("writes a sample header as a server", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen6,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen6,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, versionBigEndian)
Expect(err).ToNot(HaveOccurred())
@ -189,20 +191,35 @@ var _ = Describe("Public Header", func() {
It("writes a sample header as a client", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveClient, versionBigEndian)
Expect(err).ToNot(HaveOccurred())
Expect(b.Bytes()).To(Equal([]byte{0x38, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x13, 0x37}))
})
It("refuses to write a Public Header if the connection ID has the wrong length", func() {
It("refuses to write a Public Header if the source and destination connection IDs are not matching", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7},
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen2,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1},
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveClient, versionBigEndian)
Expect(err).To(MatchError("PublicHeader: SrcConnectionID must be equal to DestConnectionID"))
})
It("refuses to write a Public Header if the connection ID has the wrong length", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7}
hdr := Header{
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen2,
}
b := &bytes.Buffer{}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever)
@ -210,9 +227,11 @@ var _ = Describe("Public Header", func() {
})
It("refuses to write a Public Header if the PacketNumberLen is not set", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
hdr := Header{
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 2,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 2,
}
b := &bytes.Buffer{}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever)
@ -220,9 +239,11 @@ var _ = Describe("Public Header", func() {
})
It("omits the connection ID", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
DestConnectionID: connID,
SrcConnectionID: connID,
OmitConnectionID: true,
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 1,
@ -235,7 +256,8 @@ var _ = Describe("Public Header", func() {
It("writes diversification nonces", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen1,
DiversificationNonce: bytes.Repeat([]byte{1}, 32),
@ -262,10 +284,11 @@ var _ = Describe("Public Header", func() {
It("doesn't write Version Negotiation Packets", func() {
b := &bytes.Buffer{}
hdr := Header{
VersionFlag: true,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen6,
VersionFlag: true,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen6,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(err).To(MatchError("PublicHeader: Writing of Version Negotiation Packets not supported"))
@ -274,11 +297,12 @@ var _ = Describe("Public Header", func() {
It("writes packets with Version Flag, as a client", func() {
b := &bytes.Buffer{}
hdr := Header{
VersionFlag: true,
Version: protocol.Version39,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen1,
VersionFlag: true,
Version: protocol.Version39,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen1,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveClient, protocol.VersionWhatever)
Expect(err).ToNot(HaveOccurred())
@ -294,9 +318,11 @@ var _ = Describe("Public Header", func() {
Context("PublicReset packets", func() {
It("sets the Reset Flag", func() {
b := &bytes.Buffer{}
connID := protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}
hdr := Header{
ResetFlag: true,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
ResetFlag: true,
DestConnectionID: connID,
SrcConnectionID: connID,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(err).ToNot(HaveOccurred())
@ -308,11 +334,13 @@ var _ = Describe("Public Header", func() {
It("doesn't add a packet number for headers with Reset Flag sent as a client", func() {
b := &bytes.Buffer{}
connID := protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}
hdr := Header{
ResetFlag: true,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen6,
ResetFlag: true,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen6,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveClient, protocol.VersionWhatever)
Expect(err).ToNot(HaveOccurred())
@ -339,8 +367,9 @@ var _ = Describe("Public Header", func() {
It("errors when PacketNumberLen is not set", func() {
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xdecafbad,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0xdecafbad,
}
_, err := hdr.getPublicHeaderLength(protocol.PerspectiveServer)
Expect(err).To(MatchError(errPacketNumberLenNotSet))
@ -348,9 +377,10 @@ var _ = Describe("Public Header", func() {
It("gets the length of a packet with longest packet number length and connectionID", func() {
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen6,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen6,
}
length, err := hdr.getPublicHeaderLength(protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
@ -359,7 +389,8 @@ var _ = Describe("Public Header", func() {
It("gets the lengths of a packet sent by the client with the VersionFlag set", func() {
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
DestConnectionID: connID,
SrcConnectionID: connID,
OmitConnectionID: true,
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen6,
@ -373,7 +404,8 @@ var _ = Describe("Public Header", func() {
It("gets the length of a packet with longest packet number length and omitted connectionID", func() {
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
DestConnectionID: connID,
SrcConnectionID: connID,
OmitConnectionID: true,
PacketNumber: 0xDECAFBAD,
PacketNumberLen: protocol.PacketNumberLen6,
@ -385,9 +417,10 @@ var _ = Describe("Public Header", func() {
It("gets the length of a packet 2 byte packet number length ", func() {
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xDECAFBAD,
PacketNumberLen: protocol.PacketNumberLen2,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0xDECAFBAD,
PacketNumberLen: protocol.PacketNumberLen2,
}
length, err := hdr.getPublicHeaderLength(protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
@ -406,8 +439,9 @@ var _ = Describe("Public Header", func() {
It("gets the length of a PublicReset", func() {
hdr := Header{
ResetFlag: true,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
ResetFlag: true,
DestConnectionID: connID,
SrcConnectionID: connID,
}
length, err := hdr.getPublicHeaderLength(protocol.PerspectiveServer)
Expect(err).NotTo(HaveOccurred())
@ -419,8 +453,9 @@ var _ = Describe("Public Header", func() {
It("doesn't write a header if the packet number length is not set", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xDECAFBAD,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0xDECAFBAD,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(err).To(MatchError("PublicHeader: PacketNumberLen not set"))
@ -432,9 +467,10 @@ var _ = Describe("Public Header", func() {
It("writes a header with a 1-byte packet number", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen1,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen1,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, version)
Expect(err).ToNot(HaveOccurred())
@ -444,9 +480,10 @@ var _ = Describe("Public Header", func() {
It("writes a header with a 2-byte packet number", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen2,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen2,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, version)
Expect(err).ToNot(HaveOccurred())
@ -456,9 +493,10 @@ var _ = Describe("Public Header", func() {
It("writes a header with a 4-byte packet number", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0x13decafbad,
PacketNumberLen: protocol.PacketNumberLen4,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0x13decafbad,
PacketNumberLen: protocol.PacketNumberLen4,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, version)
Expect(err).ToNot(HaveOccurred())
@ -468,9 +506,10 @@ var _ = Describe("Public Header", func() {
It("writes a header with a 6-byte packet number", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xbe1337decafbad,
PacketNumberLen: protocol.PacketNumberLen6,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0xbe1337decafbad,
PacketNumberLen: protocol.PacketNumberLen6,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, version)
Expect(err).ToNot(HaveOccurred())
@ -499,10 +538,11 @@ var _ = Describe("Public Header", func() {
It("logs a Public Header containing a connection ID", func() {
(&Header{
ConnectionID: protocol.ConnectionID{0x13, 0x37, 0, 0, 0xde, 0xca, 0xfb, 0xad},
PacketNumber: 0x1337,
PacketNumberLen: 6,
Version: protocol.Version39,
DestConnectionID: protocol.ConnectionID{0x13, 0x37, 0, 0, 0xde, 0xca, 0xfb, 0xad},
SrcConnectionID: protocol.ConnectionID{0x13, 0x37, 0, 0, 0xde, 0xca, 0xfb, 0xad},
PacketNumber: 0x1337,
PacketNumberLen: 6,
Version: protocol.Version39,
}).logPublicHeader(logger)
Expect(buf.String()).To(ContainSubstring("Public Header{ConnectionID: 0x13370000decafbad, PacketNumber: 0x1337, PacketNumberLen: 6, Version: gQUIC 39"))
})
@ -528,7 +568,8 @@ var _ = Describe("Public Header", func() {
It("logs diversification nonces", func() {
(&Header{
ConnectionID: []byte{0x13, 0x13, 0, 0, 0xde, 0xca, 0xfb, 0xad},
DestConnectionID: []byte{0x13, 0x13, 0, 0, 0xde, 0xca, 0xfb, 0xad},
SrcConnectionID: []byte{0x13, 0x13, 0, 0, 0xde, 0xca, 0xfb, 0xad},
DiversificationNonce: []byte{0xba, 0xdf, 0x00, 0x0d},
}).logPublicHeader(logger)
Expect(buf.String()).To(ContainSubstring("DiversificationNonce: []byte{0xba, 0xdf, 0x0, 0xd}"))

View file

@ -20,16 +20,22 @@ func ComposeGQUICVersionNegotiation(connID protocol.ConnectionID, versions []pro
}
// ComposeVersionNegotiation composes a Version Negotiation according to the IETF draft
func ComposeVersionNegotiation(connID protocol.ConnectionID, versions []protocol.VersionNumber) []byte {
func ComposeVersionNegotiation(destConnID, srcConnID protocol.ConnectionID, versions []protocol.VersionNumber) ([]byte, error) {
greasedVersions := protocol.GetGreasedVersions(versions)
buf := bytes.NewBuffer(make([]byte, 0, 1+8+4+len(greasedVersions)*4))
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)
buf.Write(connID)
utils.BigEndian.WriteUint32(buf, 0) // version 0
connIDLen, err := encodeConnIDLen(destConnID, srcConnID)
if err != nil {
return nil, err
}
buf.WriteByte(connIDLen)
buf.Write(destConnID)
buf.Write(srcConnID)
for _, v := range greasedVersions {
utils.BigEndian.WriteUint32(buf, uint32(v))
}
return buf.Bytes()
return buf.Bytes(), nil
}

View file

@ -16,19 +16,23 @@ var _ = Describe("Version Negotiation Packets", func() {
hdr, err := parsePublicHeader(bytes.NewReader(data), protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.DestConnectionID).To(Equal(connID))
Expect(hdr.SrcConnectionID).To(Equal(connID))
Expect(hdr.SupportedVersions).To(Equal(versions))
})
It("writes in IETF draft style", func() {
connID := protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}
srcConnID := protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}
destConnID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
versions := []protocol.VersionNumber{1001, 1003}
data := ComposeVersionNegotiation(connID, versions)
data, err := ComposeVersionNegotiation(destConnID, srcConnID, versions)
Expect(err).ToNot(HaveOccurred())
Expect(data[0] & 0x80).ToNot(BeZero())
hdr, err := parseHeader(bytes.NewReader(data), protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.IsVersionNegotiation).To(BeTrue())
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.DestConnectionID).To(Equal(destConnID))
Expect(hdr.SrcConnectionID).To(Equal(srcConnID))
Expect(hdr.Version).To(BeZero())
// the supported versions should include one reserved version number
Expect(hdr.SupportedVersions).To(HaveLen(len(versions) + 1))

View file

@ -137,7 +137,7 @@ func unpackInitialPacket(aead crypto.AEAD, hdr *wire.Header, data []byte, logger
return nil, errors.New("received stream data with non-zero offset")
}
if logger.Debug() {
logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID)
logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.DestConnectionID)
hdr.Log(logger)
wire.LogFrame(logger, frame, false)
}
@ -160,7 +160,7 @@ func packUnencryptedPacket(aead crypto.AEAD, hdr *wire.Header, f wire.Frame, per
_ = aead.Seal(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], hdr.PacketNumber, raw[:payloadStartIndex])
raw = raw[0 : buffer.Len()+aead.Overhead()]
if logger.Debug() {
logger.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(raw), hdr.ConnectionID, protocol.EncryptionUnencrypted)
logger.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(raw), hdr.SrcConnectionID, protocol.EncryptionUnencrypted)
hdr.Log(logger)
wire.LogFrame(logger, f, true)
}

View file

@ -20,11 +20,12 @@ var _ = Describe("Packing and unpacking Initial packets", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
ver := protocol.VersionTLS
hdr := &wire.Header{
IsLongHeader: true,
Type: protocol.PacketTypeRetry,
PacketNumber: 0x42,
ConnectionID: connID,
Version: ver,
IsLongHeader: true,
Type: protocol.PacketTypeRetry,
PacketNumber: 0x42,
DestConnectionID: connID,
SrcConnectionID: connID,
Version: ver,
}
BeforeEach(func() {

View file

@ -446,9 +446,10 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header
packetNumberLen := p.getPacketNumberLen(pnum)
header := &wire.Header{
ConnectionID: p.connectionID,
PacketNumber: pnum,
PacketNumberLen: packetNumberLen,
DestConnectionID: p.connectionID,
SrcConnectionID: p.connectionID,
PacketNumber: pnum,
PacketNumberLen: packetNumberLen,
}
if p.version.UsesTLS() && encLevel != protocol.EncryptionForwardSecure {

View file

@ -307,7 +307,10 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
}
hdr.Raw = packet[:len(packet)-r.Len()]
packetData := packet[len(packet)-r.Len():]
connID := hdr.ConnectionID
if hdr.IsLongHeader && !hdr.DestConnectionID.Equal(hdr.SrcConnectionID) {
return errors.New("receiving packets with different destination and source connection IDs not supported")
}
if hdr.Type == protocol.PacketTypeInitial {
if s.supportsTLS {
@ -317,7 +320,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
}
s.sessionsMutex.RLock()
session, sessionKnown := s.sessions[string(connID)]
session, sessionKnown := s.sessions[string(hdr.DestConnectionID)]
s.sessionsMutex.RUnlock()
if sessionKnown && session == nil {
@ -331,12 +334,12 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
var pr *wire.PublicReset
pr, err = wire.ParsePublicReset(r)
if err != nil {
s.logger.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.", hdr.ConnectionID)
s.logger.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.", hdr.DestConnectionID)
} else {
s.logger.Infof("Received a Public Reset for connection %x, rejected packet number: 0x%x.", hdr.ConnectionID, pr.RejectedPacketNumber)
s.logger.Infof("Received a Public Reset for connection %x, rejected packet number: 0x%x.", hdr.DestConnectionID, pr.RejectedPacketNumber)
}
} else {
s.logger.Infof("Received Public Reset for unknown connection %x.", hdr.ConnectionID)
s.logger.Infof("Received Public Reset for unknown connection %x.", hdr.DestConnectionID)
}
return nil
}
@ -345,7 +348,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
// This should only happen after a server restart, when we still receive packets for connections that we lost the state for.
// TODO(#943): implement sending of IETF draft style stateless resets
if !sessionKnown && (!hdr.VersionFlag && hdr.Type != protocol.PacketTypeInitial) {
_, err = pconn.WriteTo(wire.WritePublicReset(connID, 0, 0), remoteAddr)
_, err = pconn.WriteTo(wire.WritePublicReset(hdr.DestConnectionID, 0, 0), remoteAddr)
return err
}
@ -364,7 +367,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
return errors.New("dropping small packet with unknown version")
}
s.logger.Infof("Client offered version %s, sending Version Negotiation Packet", hdr.Version)
_, err := pconn.WriteTo(wire.ComposeGQUICVersionNegotiation(hdr.ConnectionID, s.config.Versions), remoteAddr)
_, err := pconn.WriteTo(wire.ComposeGQUICVersionNegotiation(hdr.SrcConnectionID, s.config.Versions), remoteAddr)
return err
}
@ -380,11 +383,11 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
return errors.New("Server BUG: negotiated version not supported")
}
s.logger.Infof("Serving new connection: %x, version %s from %v", hdr.ConnectionID, version, remoteAddr)
s.logger.Infof("Serving new connection: %x, version %s from %v", hdr.DestConnectionID, version, remoteAddr)
session, err = s.newSession(
&conn{pconn: pconn, currentAddr: remoteAddr},
version,
hdr.ConnectionID,
hdr.DestConnectionID,
s.scfg,
s.tlsConf,
s.config,
@ -394,10 +397,10 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
return err
}
s.sessionsMutex.Lock()
s.sessions[string(connID)] = session
s.sessions[string(hdr.DestConnectionID)] = session
s.sessionsMutex.Unlock()
s.runHandshakeAndSession(session, connID)
s.runHandshakeAndSession(session, hdr.DestConnectionID)
}
session.handlePacket(&receivedPacket{
remoteAddr: remoteAddr,

View file

@ -418,10 +418,11 @@ var _ = Describe("Server", func() {
config.Versions = []protocol.VersionNumber{99}
b := &bytes.Buffer{}
hdr := wire.Header{
VersionFlag: true,
ConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
VersionFlag: true,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
}
hdr.Write(b, protocol.PerspectiveClient, 13 /* not a valid QUIC version */)
b.Write(bytes.Repeat([]byte{0}, protocol.MinClientHelloSize)) // add a fake CHLO
@ -433,10 +434,11 @@ var _ = Describe("Server", func() {
It("doesn't respond with a version negotiation packet if the first packet is too small", func() {
b := &bytes.Buffer{}
hdr := wire.Header{
VersionFlag: true,
ConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
VersionFlag: true,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
}
hdr.Write(b, protocol.PerspectiveClient, 13 /* not a valid QUIC version */)
b.Write(bytes.Repeat([]byte{0}, protocol.MinClientHelloSize-1)) // this packet is 1 byte too small
@ -510,10 +512,11 @@ var _ = Describe("Server", func() {
connID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
b := &bytes.Buffer{}
hdr := wire.Header{
VersionFlag: true,
ConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
VersionFlag: true,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
}
hdr.Write(b, protocol.PerspectiveClient, 13 /* not a valid QUIC version */)
b.Write(bytes.Repeat([]byte{0}, protocol.MinClientHelloSize)) // add a fake CHLO
@ -535,7 +538,8 @@ var _ = Describe("Server", func() {
packet, err := wire.ParseHeaderSentByServer(r, protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred())
Expect(packet.VersionFlag).To(BeTrue())
Expect(packet.ConnectionID).To(Equal(connID))
Expect(packet.DestConnectionID).To(Equal(connID))
Expect(packet.SrcConnectionID).To(Equal(connID))
Expect(r.Len()).To(BeZero())
Consistently(done).ShouldNot(BeClosed())
// make the go routine return
@ -548,11 +552,12 @@ var _ = Describe("Server", func() {
config.Versions = append(config.Versions, protocol.VersionTLS)
b := &bytes.Buffer{}
hdr := wire.Header{
Type: protocol.PacketTypeInitial,
IsLongHeader: true,
ConnectionID: connID,
PacketNumber: 0x55,
Version: 0x1234,
Type: protocol.PacketTypeInitial,
IsLongHeader: true,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0x55,
Version: 0x1234,
}
err := hdr.Write(b, protocol.PerspectiveClient, protocol.VersionTLS)
Expect(err).ToNot(HaveOccurred())
@ -575,7 +580,8 @@ var _ = Describe("Server", func() {
packet, err := wire.ParseHeaderSentByServer(r, protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred())
Expect(packet.IsVersionNegotiation).To(BeTrue())
Expect(packet.ConnectionID).To(Equal(connID))
Expect(packet.DestConnectionID).To(Equal(connID))
Expect(packet.SrcConnectionID).To(Equal(connID))
Expect(r.Len()).To(BeZero())
Consistently(done).ShouldNot(BeClosed())
// make the go routine return
@ -587,11 +593,12 @@ var _ = Describe("Server", func() {
connID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
b := &bytes.Buffer{}
hdr := wire.Header{
Type: protocol.PacketTypeInitial,
IsLongHeader: true,
ConnectionID: connID,
PacketNumber: 0x55,
Version: protocol.VersionTLS,
Type: protocol.PacketTypeInitial,
IsLongHeader: true,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 0x55,
Version: protocol.VersionTLS,
}
err := hdr.Write(b, protocol.PerspectiveClient, protocol.VersionTLS)
Expect(err).ToNot(HaveOccurred())

View file

@ -87,6 +87,7 @@ func newServerTLS(
}
func (s *serverTLS) HandleInitial(remoteAddr net.Addr, hdr *wire.Header, data []byte) {
// TODO: add a check that DestConnID == SrcConnID
s.logger.Debugf("Received a Packet. Handling it statelessly.")
sess, err := s.handleInitialImpl(remoteAddr, hdr, data)
if err != nil {
@ -97,7 +98,7 @@ func (s *serverTLS) HandleInitial(remoteAddr net.Addr, hdr *wire.Header, data []
return
}
s.sessionChan <- tlsSession{
connID: hdr.ConnectionID,
connID: hdr.DestConnectionID,
sess: sess,
}
}
@ -116,11 +117,12 @@ func (s *serverTLS) sendConnectionClose(remoteAddr net.Addr, clientHdr *wire.Hea
ReasonPhrase: closeErr.Error(),
}
replyHdr := &wire.Header{
IsLongHeader: true,
Type: protocol.PacketTypeHandshake,
ConnectionID: clientHdr.ConnectionID, // echo the client's connection ID
PacketNumber: 1, // random packet number
Version: clientHdr.Version,
IsLongHeader: true,
Type: protocol.PacketTypeHandshake,
SrcConnectionID: clientHdr.SrcConnectionID,
DestConnectionID: clientHdr.DestConnectionID,
PacketNumber: 1, // random packet number
Version: clientHdr.Version,
}
data, err := packUnencryptedPacket(aead, replyHdr, ccf, protocol.PerspectiveServer, s.logger)
if err != nil {
@ -137,12 +139,16 @@ func (s *serverTLS) handleInitialImpl(remoteAddr net.Addr, hdr *wire.Header, dat
// check version, if not matching send VNP
if !protocol.IsSupportedVersion(s.supportedVersions, hdr.Version) {
s.logger.Debugf("Client offered version %s, sending VersionNegotiationPacket", hdr.Version)
_, err := s.conn.WriteTo(wire.ComposeVersionNegotiation(hdr.ConnectionID, s.supportedVersions), remoteAddr)
vnp, err := wire.ComposeVersionNegotiation(hdr.SrcConnectionID, hdr.DestConnectionID, s.supportedVersions)
if err != nil {
return nil, err
}
_, err = s.conn.WriteTo(vnp, remoteAddr)
return nil, err
}
// unpack packet and check stream frame contents
aead, err := crypto.NewNullAEAD(protocol.PerspectiveServer, hdr.ConnectionID, hdr.Version)
aead, err := crypto.NewNullAEAD(protocol.PerspectiveServer, hdr.DestConnectionID, protocol.VersionTLS)
if err != nil {
return nil, err
}
@ -170,15 +176,17 @@ func (s *serverTLS) handleUnpackedInitial(remoteAddr net.Addr, hdr *wire.Header,
return nil, err
}
alert := tls.Handshake()
s.logger.Debugf("%#v\n", hdr)
if alert == mint.AlertStatelessRetry {
// the HelloRetryRequest was written to the bufferConn
// Take that data and write send a Retry packet
replyHdr := &wire.Header{
IsLongHeader: true,
Type: protocol.PacketTypeRetry,
ConnectionID: hdr.ConnectionID, // echo the client's connection ID
PacketNumber: hdr.PacketNumber, // echo the client's packet number
Version: version,
IsLongHeader: true,
Type: protocol.PacketTypeRetry,
DestConnectionID: hdr.DestConnectionID,
SrcConnectionID: hdr.SrcConnectionID,
PacketNumber: hdr.PacketNumber, // echo the client's packet number
Version: version,
}
f := &wire.StreamFrame{
StreamID: version.CryptoStreamID(),
@ -206,7 +214,7 @@ func (s *serverTLS) handleUnpackedInitial(remoteAddr net.Addr, hdr *wire.Header,
params := <-paramsChan
sess, err := newTLSServerSession(
&conn{pconn: s.conn, currentAddr: remoteAddr},
hdr.ConnectionID, // TODO: we can use a server-chosen connection ID here
hdr.DestConnectionID, // TODO(#1003): we can use a server-chosen connection ID here
protocol.PacketNumber(1), // TODO: use a random packet number here
s.config,
tls,

View file

@ -49,10 +49,11 @@ var _ = Describe("Stateless TLS handling", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
hdrBuf := &bytes.Buffer{}
hdr := &wire.Header{
IsLongHeader: true,
ConnectionID: connID,
PacketNumber: 1,
Version: protocol.VersionTLS,
IsLongHeader: true,
DestConnectionID: connID,
SrcConnectionID: connID,
PacketNumber: 1,
Version: protocol.VersionTLS,
}
err := hdr.Write(hdrBuf, protocol.PerspectiveClient, protocol.VersionTLS)
Expect(err).ToNot(HaveOccurred())
@ -74,7 +75,7 @@ var _ = Describe("Stateless TLS handling", func() {
hdr, err := wire.ParseHeaderSentByServer(r, protocol.VersionTLS)
Expect(err).ToNot(HaveOccurred())
hdr.Raw = data[:len(data)-r.Len()]
aead, err := crypto.NewNullAEAD(protocol.PerspectiveClient, hdr.ConnectionID, protocol.VersionTLS)
aead, err := crypto.NewNullAEAD(protocol.PerspectiveClient, hdr.DestConnectionID, protocol.VersionTLS)
Expect(err).ToNot(HaveOccurred())
payload, err := aead.Open(nil, data[len(data)-r.Len():], hdr.PacketNumber, hdr.Raw)
Expect(err).ToNot(HaveOccurred())
@ -83,8 +84,9 @@ var _ = Describe("Stateless TLS handling", func() {
It("sends a version negotiation packet if it doesn't support the version", func() {
hdr := &wire.Header{
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
Version: 0x1337,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
Version: 0x1337,
}
server.HandleInitial(nil, hdr, bytes.Repeat([]byte{0}, protocol.MinInitialPacketSize))
Expect(conn.dataWritten.Len()).ToNot(BeZero())

View file

@ -598,9 +598,9 @@ func (s *session) handlePacketImpl(p *receivedPacket) error {
packet, err := s.unpacker.Unpack(hdr.Raw, hdr, data)
if s.logger.Debug() {
if err != nil {
s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID)
s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.DestConnectionID)
} else {
s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID, packet.encryptionLevel)
s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.DestConnectionID, packet.encryptionLevel)
}
hdr.Log(s.logger)
}