parse the packet header before getting the session from the session map

This commit is contained in:
Marten Seemann 2017-11-09 20:52:52 +07:00
parent dd722758af
commit 5d4174b2f0
8 changed files with 144 additions and 173 deletions

View file

@ -249,7 +249,7 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
rcvTime := time.Now() rcvTime := time.Now()
r := bytes.NewReader(packet) r := bytes.NewReader(packet)
hdr, err := wire.ParseHeader(r, protocol.PerspectiveServer, c.version) hdr, err := wire.ParseHeaderSentByServer(r, c.version)
if err != nil { if err != nil {
utils.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error()) utils.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error())
// drop this packet if we can't parse the header // drop this packet if we can't parse the header

View file

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"github.com/lucas-clemente/quic-go/internal/protocol" "github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
) )
// Header is the header of a QUIC packet. // Header is the header of a QUIC packet.
@ -32,59 +31,56 @@ type Header struct {
isPublicHeader bool isPublicHeader bool
} }
// ParseHeader parses the header. // ParseHeaderSentByServer parses the header for a packet that was sent by the server.
func ParseHeader(b *bytes.Reader, sentBy protocol.Perspective, version protocol.VersionNumber) (*Header, error) { func ParseHeaderSentByServer(b *bytes.Reader, version protocol.VersionNumber) (*Header, error) {
var typeByte uint8 typeByte, err := b.ReadByte()
if version == protocol.VersionUnknown {
var err error
typeByte, err = b.ReadByte()
if err != nil {
return nil, err
}
_ = b.UnreadByte() // unread the type byte
}
// There are two conditions this is a header in the IETF Header format:
// 1. We already know the version (because this is a packet that belongs to an exisitng session).
// 2. If this is a new packet, it must have the Long Format, which has the 0x80 bit set (which is always 0 in gQUIC).
// There's a third option: This could be a packet with Short Format that arrives after a server lost state.
// In that case, we'll try parsing the header as a gQUIC Public Header.
if version.UsesTLS() || (version == protocol.VersionUnknown && typeByte&0x80 > 0) {
return parseHeader(b, sentBy)
}
// This is a gQUIC Public Header.
hdr, err := parsePublicHeader(b, sentBy, version)
if err != nil { if err != nil {
return nil, err return nil, err
} }
hdr.isPublicHeader = true // save that this is a Public Header, so we can log it correctly later _ = b.UnreadByte() // unread the type byte
return hdr, nil
var isPublicHeader bool
// As a client, we know the version of the packet that the server sent, except for Version Negotiation Packets.
// Both gQUIC and IETF QUIC Version Negotiation Packets have 0x1 set.
if typeByte&0x1 > 0 {
// IETF QUIC Version Negotiation Packets are sent with the Long Header (indicated by the 0x80 bit)
// gQUIC always has 0x80 unset
isPublicHeader = typeByte&0x80 == 0
} else {
// For all packets that are not Version Negotiation Packets, the client knows the version that this packet was sent with
isPublicHeader = !version.UsesTLS()
}
return parsePacketHeader(b, protocol.PerspectiveServer, isPublicHeader)
} }
// PeekConnectionID parses the connection ID from a QUIC packet's public header, sent by the client. // ParseHeaderSentByClient parses the header for a packet that was sent by the client.
// This function should not be called for packets sent by the server, since on these packets the Connection ID could be omitted. func ParseHeaderSentByClient(b *bytes.Reader) (*Header, error) {
// If no error occurs, it restores the read position in the bytes.Reader. typeByte, err := b.ReadByte()
func PeekConnectionID(b *bytes.Reader) (protocol.ConnectionID, error) {
var connectionID protocol.ConnectionID
if _, err := b.ReadByte(); err != nil {
return 0, err
}
// unread the public flag byte
defer b.UnreadByte()
// Assume that the packet contains the Connection ID.
// This is a valid assumption for all packets sent by the client, because the server doesn't allow the ommision of the Connection ID.
connID, err := utils.BigEndian.ReadUint64(b)
if err != nil { if err != nil {
return 0, err return nil, err
} }
connectionID = protocol.ConnectionID(connID) _ = b.UnreadByte() // unread the type byte
// unread the connection ID
for i := 0; i < 8; i++ { // If this is a gQUIC header 0x80 and 0x40 will be set to 0.
b.UnreadByte() // If this is an IETF QUIC header there are two options:
// * either 0x80 will be 1 (for the Long Header)
// * or 0x40 (the Connection ID Flag) will be 0 (for the Short Header), since we don't the client to omit it
isPublicHeader := typeByte&0xc0 == 0
return parsePacketHeader(b, protocol.PerspectiveClient, isPublicHeader)
}
func parsePacketHeader(b *bytes.Reader, sentBy protocol.Perspective, isPublicHeader bool) (*Header, error) {
// This is a gQUIC Public Header.
if isPublicHeader {
hdr, err := parsePublicHeader(b, sentBy)
if err != nil {
return nil, err
}
hdr.isPublicHeader = true // save that this is a Public Header, so we can log it correctly later
return hdr, nil
} }
return connectionID, nil return parseHeader(b, sentBy)
} }
// Write writes the Header. // Write writes the Header.

View file

@ -18,29 +18,6 @@ var _ = Describe("Header", func() {
versionIETFHeader = protocol.VersionTLS // a QUIC version taht uses the IETF Header format versionIETFHeader = protocol.VersionTLS // a QUIC version taht uses the IETF Header format
) )
Context("peeking the connection ID", func() {
It("gets the connection ID", func() {
b := bytes.NewReader([]byte{0x09, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0x51, 0x30, 0x33, 0x34, 0x01})
len := b.Len()
connID, err := PeekConnectionID(b)
Expect(err).ToNot(HaveOccurred())
Expect(connID).To(Equal(protocol.ConnectionID(0x4cfa9f9b668619f6)))
Expect(b.Len()).To(Equal(len))
})
It("errors if the header is too short", func() {
b := bytes.NewReader([]byte{0x09, 0xf6, 0x19, 0x86, 0x66, 0x9b})
_, err := PeekConnectionID(b)
Expect(err).To(HaveOccurred())
})
It("errors if the header is empty", func() {
b := bytes.NewReader([]byte{})
_, err := PeekConnectionID(b)
Expect(err).To(HaveOccurred())
})
})
Context("parsing", func() { Context("parsing", func() {
It("parses an IETF draft header, when the QUIC version supports TLS", func() { It("parses an IETF draft header, when the QUIC version supports TLS", func() {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -52,7 +29,7 @@ var _ = Describe("Header", func() {
PacketNumberLen: protocol.PacketNumberLen2, PacketNumberLen: protocol.PacketNumberLen2,
}).writeHeader(buf) }).writeHeader(buf)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeader(bytes.NewReader(buf.Bytes()), protocol.PerspectiveClient, versionIETFHeader) hdr, err := ParseHeaderSentByClient(bytes.NewReader(buf.Bytes()))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.KeyPhase).To(BeEquivalentTo(1)) Expect(hdr.KeyPhase).To(BeEquivalentTo(1))
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x42))) Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x42)))
@ -67,7 +44,7 @@ var _ = Describe("Header", func() {
PacketNumber: 0x42, PacketNumber: 0x42,
}).writeHeader(buf) }).writeHeader(buf)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeader(bytes.NewReader(buf.Bytes()), protocol.PerspectiveClient, protocol.VersionUnknown) hdr, err := ParseHeaderSentByClient(bytes.NewReader(buf.Bytes()))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.Type).To(Equal(protocol.PacketType0RTT)) Expect(hdr.Type).To(Equal(protocol.PacketType0RTT))
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x42))) Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x42)))
@ -84,7 +61,7 @@ var _ = Describe("Header", func() {
PacketNumberLen: protocol.PacketNumberLen6, PacketNumberLen: protocol.PacketNumberLen6,
}).writePublicHeader(buf, protocol.PerspectiveClient, versionPublicHeader) }).writePublicHeader(buf, protocol.PerspectiveClient, versionPublicHeader)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeader(bytes.NewReader(buf.Bytes()), protocol.PerspectiveClient, protocol.VersionUnknown) hdr, err := ParseHeaderSentByClient(bytes.NewReader(buf.Bytes()))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x1337))) Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x1337)))
Expect(hdr.Version).To(Equal(versionPublicHeader)) Expect(hdr.Version).To(Equal(versionPublicHeader))
@ -100,7 +77,7 @@ var _ = Describe("Header", func() {
DiversificationNonce: bytes.Repeat([]byte{'f'}, 32), DiversificationNonce: bytes.Repeat([]byte{'f'}, 32),
}).writePublicHeader(buf, protocol.PerspectiveServer, versionPublicHeader) }).writePublicHeader(buf, protocol.PerspectiveServer, versionPublicHeader)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
hdr, err := ParseHeader(bytes.NewReader(buf.Bytes()), protocol.PerspectiveServer, versionPublicHeader) hdr, err := ParseHeaderSentByServer(bytes.NewReader(buf.Bytes()), versionPublicHeader)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x1337))) Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x1337)))
Expect(hdr.DiversificationNonce).To(HaveLen(32)) Expect(hdr.DiversificationNonce).To(HaveLen(32))
@ -117,13 +94,37 @@ var _ = Describe("Header", func() {
PacketNumberLen: protocol.PacketNumberLen6, PacketNumberLen: protocol.PacketNumberLen6,
}).writePublicHeader(buf, protocol.PerspectiveClient, versionPublicHeader) }).writePublicHeader(buf, protocol.PerspectiveClient, versionPublicHeader)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
_, err = ParseHeader(bytes.NewReader(buf.Bytes()[0:12]), protocol.PerspectiveClient, protocol.VersionUnknown) _, err = ParseHeaderSentByClient(bytes.NewReader(buf.Bytes()[0:12]))
Expect(err).To(MatchError(io.EOF)) Expect(err).To(MatchError(io.EOF))
}) })
It("errors when given no data", func() { It("errors when given no data", func() {
_, err := ParseHeader(bytes.NewReader([]byte{}), protocol.PerspectiveClient, protocol.VersionUnknown) _, err := ParseHeaderSentByServer(bytes.NewReader([]byte{}), protocol.VersionUnknown)
Expect(err).To(MatchError(io.EOF)) Expect(err).To(MatchError(io.EOF))
_, err = ParseHeaderSentByClient(bytes.NewReader([]byte{}))
Expect(err).To(MatchError(io.EOF))
})
It("parses a gQUIC Version Negotiation Packet", func() {
versions := []protocol.VersionNumber{0x13, 0x37}
data := ComposeGQUICVersionNegotiation(0x42, versions)
hdr, err := ParseHeaderSentByServer(bytes.NewReader(data), protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.isPublicHeader).To(BeTrue())
Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID(0x42)))
Expect(hdr.SupportedVersions).To(Equal(versions))
})
It("parses a gQUIC Version Negotiation Packet", func() {
versions := []protocol.VersionNumber{0x13, 0x37}
data := ComposeVersionNegotiation(0x42, 0x77, versions)
hdr, err := ParseHeaderSentByServer(bytes.NewReader(data), protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.isPublicHeader).To(BeFalse())
Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID(0x42)))
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x77)))
Expect(hdr.SupportedVersions).To(Equal(versions))
Expect(hdr.Type).To(Equal(protocol.PacketTypeVersionNegotiation))
}) })
}) })
@ -137,7 +138,7 @@ var _ = Describe("Header", func() {
} }
err := hdr.Write(buf, protocol.PerspectiveServer, versionPublicHeader) err := hdr.Write(buf, protocol.PerspectiveServer, versionPublicHeader)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
_, err = parsePublicHeader(bytes.NewReader(buf.Bytes()), protocol.PerspectiveServer, versionPublicHeader) _, err = parsePublicHeader(bytes.NewReader(buf.Bytes()), protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.isPublicHeader).To(BeTrue()) Expect(hdr.isPublicHeader).To(BeTrue())
}) })

View file

@ -12,9 +12,6 @@ import (
) )
var ( var (
// ErrPacketWithUnknownVersion occurs when a packet with an unknown version is parsed.
// This can happen when the server is restarted. The client will send a packet without a version number.
ErrPacketWithUnknownVersion = errors.New("PublicHeader: Received a packet without version number, that we don't know the version for")
errResetAndVersionFlagSet = errors.New("PublicHeader: Reset Flag and Version Flag should not be set at the same time") errResetAndVersionFlagSet = errors.New("PublicHeader: Reset Flag and Version Flag should not be set at the same time")
errReceivedOmittedConnectionID = qerr.Error(qerr.InvalidPacketHeader, "receiving packets with omitted ConnectionID is not supported") errReceivedOmittedConnectionID = qerr.Error(qerr.InvalidPacketHeader, "receiving packets with omitted ConnectionID is not supported")
errInvalidConnectionID = qerr.Error(qerr.InvalidPacketHeader, "connection ID cannot be 0") errInvalidConnectionID = qerr.Error(qerr.InvalidPacketHeader, "connection ID cannot be 0")
@ -90,7 +87,7 @@ func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, v
// parsePublicHeader parses a QUIC packet's Public Header. // parsePublicHeader parses a QUIC packet's Public Header.
// The packetSentBy is the perspective of the peer that sent this PublicHeader, i.e. if we're the server, packetSentBy should be PerspectiveClient. // The packetSentBy is the perspective of the peer that sent this PublicHeader, i.e. if we're the server, packetSentBy should be PerspectiveClient.
func parsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective, version protocol.VersionNumber) (*Header, error) { func parsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Header, error) {
header := &Header{} header := &Header{}
// First byte // First byte
@ -100,9 +97,6 @@ func parsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective, versi
} }
header.ResetFlag = publicFlagByte&0x02 > 0 header.ResetFlag = publicFlagByte&0x02 > 0
header.VersionFlag = publicFlagByte&0x01 > 0 header.VersionFlag = publicFlagByte&0x01 > 0
if version == protocol.VersionUnknown && !(header.VersionFlag || header.ResetFlag) {
return nil, ErrPacketWithUnknownVersion
}
// TODO: activate this check once Chrome sends the correct value // TODO: activate this check once Chrome sends the correct value
// see https://github.com/lucas-clemente/quic-go/issues/232 // see https://github.com/lucas-clemente/quic-go/issues/232
@ -181,12 +175,11 @@ func parsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective, versi
return nil, err return nil, err
} }
header.Version = protocol.VersionNumber(versionTag) header.Version = protocol.VersionNumber(versionTag)
version = header.Version
} }
// Packet number // Packet number
if header.hasPacketNumber(packetSentBy) { if header.hasPacketNumber(packetSentBy) {
packetNumber, err := utils.GetByteOrder(version).ReadUintN(b, uint8(header.PacketNumberLen)) packetNumber, err := utils.BigEndian.ReadUintN(b, uint8(header.PacketNumberLen))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -19,7 +19,7 @@ var _ = Describe("Public Header", func() {
ver := make([]byte, 4) ver := make([]byte, 4)
binary.BigEndian.PutUint32(ver, uint32(protocol.SupportedVersions[0])) binary.BigEndian.PutUint32(ver, uint32(protocol.SupportedVersions[0]))
b := bytes.NewReader(append(append([]byte{0x09, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}, ver...), 0x01)) b := bytes.NewReader(append(append([]byte{0x09, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}, ver...), 0x01))
hdr, err := parsePublicHeader(b, protocol.PerspectiveClient, protocol.VersionUnknown) hdr, err := parsePublicHeader(b, protocol.PerspectiveClient)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.VersionFlag).To(BeTrue()) Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.ResetFlag).To(BeFalse()) Expect(hdr.ResetFlag).To(BeFalse())
@ -32,13 +32,13 @@ var _ = Describe("Public Header", func() {
It("does not accept an omittedd connection ID as a server", func() { It("does not accept an omittedd connection ID as a server", func() {
b := bytes.NewReader([]byte{0x00, 0x01}) b := bytes.NewReader([]byte{0x00, 0x01})
_, err := parsePublicHeader(b, protocol.PerspectiveClient, protocol.VersionWhatever) _, err := parsePublicHeader(b, protocol.PerspectiveClient)
Expect(err).To(MatchError(errReceivedOmittedConnectionID)) Expect(err).To(MatchError(errReceivedOmittedConnectionID))
}) })
It("accepts aan d connection ID as a client", func() { It("accepts aan d connection ID as a client", func() {
b := bytes.NewReader([]byte{0x00, 0x01}) b := bytes.NewReader([]byte{0x00, 0x01})
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever) hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.OmitConnectionID).To(BeTrue()) Expect(hdr.OmitConnectionID).To(BeTrue())
Expect(hdr.ConnectionID).To(BeZero()) Expect(hdr.ConnectionID).To(BeZero())
@ -47,13 +47,13 @@ var _ = Describe("Public Header", func() {
It("rejects 0 as a connection ID", func() { It("rejects 0 as a connection ID", func() {
b := bytes.NewReader([]byte{0x09, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x51, 0x30, 0x33, 0x30, 0x01}) b := bytes.NewReader([]byte{0x09, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x51, 0x30, 0x33, 0x30, 0x01})
_, err := parsePublicHeader(b, protocol.PerspectiveClient, protocol.VersionUnknown) _, err := parsePublicHeader(b, protocol.PerspectiveClient)
Expect(err).To(MatchError(errInvalidConnectionID)) Expect(err).To(MatchError(errInvalidConnectionID))
}) })
It("reads a PublicReset packet", func() { It("reads a PublicReset packet", func() {
b := bytes.NewReader([]byte{0xa, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}) b := bytes.NewReader([]byte{0xa, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8})
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionUnknown) hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.ResetFlag).To(BeTrue()) Expect(hdr.ResetFlag).To(BeTrue())
Expect(hdr.ConnectionID).ToNot(BeZero()) Expect(hdr.ConnectionID).ToNot(BeZero())
@ -61,7 +61,7 @@ var _ = Describe("Public Header", func() {
It("parses a public reset packet", func() { It("parses a public reset packet", func() {
b := bytes.NewReader([]byte{0xa, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}) b := bytes.NewReader([]byte{0xa, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08})
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionUnknown) hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.ResetFlag).To(BeTrue()) Expect(hdr.ResetFlag).To(BeTrue())
Expect(hdr.VersionFlag).To(BeFalse()) Expect(hdr.VersionFlag).To(BeFalse())
@ -72,25 +72,19 @@ var _ = Describe("Public Header", func() {
divNonce := []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} divNonce := []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}
Expect(divNonce).To(HaveLen(32)) Expect(divNonce).To(HaveLen(32))
b := bytes.NewReader(append(append([]byte{0x0c, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c}, divNonce...), 0x37)) b := bytes.NewReader(append(append([]byte{0x0c, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c}, divNonce...), 0x37))
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever) hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.ConnectionID).To(Not(BeZero())) Expect(hdr.ConnectionID).To(Not(BeZero()))
Expect(hdr.DiversificationNonce).To(Equal(divNonce)) Expect(hdr.DiversificationNonce).To(Equal(divNonce))
Expect(b.Len()).To(BeZero()) Expect(b.Len()).To(BeZero())
}) })
It("returns an unknown version error when receiving a packet without a version for which the version is not given", func() {
b := bytes.NewReader([]byte{0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xef})
_, err := parsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionUnknown)
Expect(err).To(MatchError(ErrPacketWithUnknownVersion))
})
PIt("rejects diversification nonces sent by the client", func() { PIt("rejects diversification nonces sent by the client", func() {
b := bytes.NewReader([]byte{0x0c, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, b := bytes.NewReader([]byte{0x0c, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
0x01, 0x01,
}) })
_, err := parsePublicHeader(b, protocol.PerspectiveClient, protocol.VersionWhatever) _, err := parsePublicHeader(b, protocol.PerspectiveClient)
Expect(err).To(MatchError("diversification nonces should only be sent by servers")) Expect(err).To(MatchError("diversification nonces should only be sent by servers"))
}) })
@ -103,7 +97,7 @@ var _ = Describe("Public Header", func() {
It("parses version negotiation packets sent by the server", func() { It("parses version negotiation packets sent by the server", func() {
b := bytes.NewReader(ComposeGQUICVersionNegotiation(0x1337, protocol.SupportedVersions)) b := bytes.NewReader(ComposeGQUICVersionNegotiation(0x1337, protocol.SupportedVersions))
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionUnknown) hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.VersionFlag).To(BeTrue()) Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.Version).To(BeZero()) // unitialized Expect(hdr.Version).To(BeZero()) // unitialized
@ -113,7 +107,7 @@ var _ = Describe("Public Header", func() {
It("errors if it doesn't contain any versions", func() { It("errors if it doesn't contain any versions", func() {
b := bytes.NewReader([]byte{0x9, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c}) b := bytes.NewReader([]byte{0x9, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c})
_, err := parsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionUnknown) _, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).To(MatchError("InvalidVersionNegotiationPacket: empty version list")) Expect(err).To(MatchError("InvalidVersionNegotiationPacket: empty version list"))
}) })
@ -123,7 +117,7 @@ var _ = Describe("Public Header", func() {
data = appendVersion(data, protocol.SupportedVersions[0]) data = appendVersion(data, protocol.SupportedVersions[0])
data = appendVersion(data, 99) // unsupported version data = appendVersion(data, 99) // unsupported version
b := bytes.NewReader(data) b := bytes.NewReader(data)
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionUnknown) hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.VersionFlag).To(BeTrue()) Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.SupportedVersions).To(Equal([]protocol.VersionNumber{1, protocol.SupportedVersions[0], 99})) Expect(hdr.SupportedVersions).To(Equal([]protocol.VersionNumber{1, protocol.SupportedVersions[0], 99}))
@ -134,54 +128,46 @@ var _ = Describe("Public Header", func() {
data := ComposeGQUICVersionNegotiation(0x1337, protocol.SupportedVersions) data := ComposeGQUICVersionNegotiation(0x1337, protocol.SupportedVersions)
data = append(data, []byte{0x13, 0x37}...) data = append(data, []byte{0x13, 0x37}...)
b := bytes.NewReader(data) b := bytes.NewReader(data)
_, err := parsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionUnknown) _, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).To(MatchError(qerr.InvalidVersionNegotiationPacket)) Expect(err).To(MatchError(qerr.InvalidVersionNegotiationPacket))
}) })
}) })
Context("Packet Number lengths", func() { Context("Packet Number lengths", func() {
Context("in big endian encoding", func() { It("accepts 1-byte packet numbers", func() {
version := protocol.Version39 b := bytes.NewReader([]byte{0x08, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0xde})
hdr, err := parsePublicHeader(b, protocol.PerspectiveClient)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0xde)))
Expect(hdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen1))
Expect(b.Len()).To(BeZero())
})
BeforeEach(func() { It("accepts 2-byte packet numbers", func() {
Expect(utils.GetByteOrder(version)).To(Equal(utils.BigEndian)) b := bytes.NewReader([]byte{0x18, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0xde, 0xca})
}) hdr, err := parsePublicHeader(b, protocol.PerspectiveClient)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0xdeca)))
Expect(hdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen2))
Expect(b.Len()).To(BeZero())
})
It("accepts 1-byte packet numbers", func() { It("accepts 4-byte packet numbers", func() {
b := bytes.NewReader([]byte{0x08, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0xde}) b := bytes.NewReader([]byte{0x28, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0xad, 0xfb, 0xca, 0xde})
hdr, err := parsePublicHeader(b, protocol.PerspectiveClient, version) hdr, err := parsePublicHeader(b, protocol.PerspectiveClient)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0xde))) Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0xadfbcade)))
Expect(hdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen1)) Expect(hdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen4))
Expect(b.Len()).To(BeZero()) Expect(b.Len()).To(BeZero())
}) })
It("accepts 2-byte packet numbers", func() { It("accepts 6-byte packet numbers", func() {
b := bytes.NewReader([]byte{0x18, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0xde, 0xca}) b := bytes.NewReader([]byte{0x38, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0x23, 0x42, 0xad, 0xfb, 0xca, 0xde})
hdr, err := parsePublicHeader(b, protocol.PerspectiveClient, version) hdr, err := parsePublicHeader(b, protocol.PerspectiveClient)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0xdeca))) Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x2342adfbcade)))
Expect(hdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen2)) Expect(hdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen6))
Expect(b.Len()).To(BeZero()) Expect(b.Len()).To(BeZero())
})
It("accepts 4-byte packet numbers", func() {
b := bytes.NewReader([]byte{0x28, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0xad, 0xfb, 0xca, 0xde})
hdr, err := parsePublicHeader(b, protocol.PerspectiveClient, version)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0xadfbcade)))
Expect(hdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen4))
Expect(b.Len()).To(BeZero())
})
It("accepts 6-byte packet numbers", func() {
b := bytes.NewReader([]byte{0x38, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0x23, 0x42, 0xad, 0xfb, 0xca, 0xde})
hdr, err := parsePublicHeader(b, protocol.PerspectiveClient, version)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(0x2342adfbcade)))
Expect(hdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen6))
Expect(b.Len()).To(BeZero())
})
}) })
}) })
}) })

View file

@ -12,7 +12,7 @@ var _ = Describe("Version Negotiation Packets", func() {
It("writes for gQUIC", func() { It("writes for gQUIC", func() {
versions := []protocol.VersionNumber{1001, 1003} versions := []protocol.VersionNumber{1001, 1003}
data := ComposeGQUICVersionNegotiation(0x1337, versions) data := ComposeGQUICVersionNegotiation(0x1337, versions)
hdr, err := parsePublicHeader(bytes.NewReader(data), protocol.PerspectiveServer, protocol.VersionUnknown) hdr, err := parsePublicHeader(bytes.NewReader(data), protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(hdr.VersionFlag).To(BeTrue()) Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID(0x1337))) Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID(0x1337)))

View file

@ -219,38 +219,25 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
rcvTime := time.Now() rcvTime := time.Now()
r := bytes.NewReader(packet) r := bytes.NewReader(packet)
connID, err := wire.PeekConnectionID(r) hdr, err := wire.ParseHeaderSentByClient(r)
if err != nil {
return qerr.Error(qerr.InvalidPacketHeader, err.Error())
}
s.sessionsMutex.RLock()
session, ok := s.sessions[connID]
s.sessionsMutex.RUnlock()
if ok && session == nil {
// Late packet for closed session
return nil
}
version := protocol.VersionUnknown
if ok {
version = session.GetVersion()
}
hdr, err := wire.ParseHeader(r, protocol.PerspectiveClient, version)
if err == wire.ErrPacketWithUnknownVersion {
_, err = pconn.WriteTo(wire.WritePublicReset(connID, 0, 0), remoteAddr)
return err
}
if err != nil { if err != nil {
return qerr.Error(qerr.InvalidPacketHeader, err.Error()) return qerr.Error(qerr.InvalidPacketHeader, err.Error())
} }
hdr.Raw = packet[:len(packet)-r.Len()] hdr.Raw = packet[:len(packet)-r.Len()]
connID := hdr.ConnectionID
s.sessionsMutex.RLock()
session, sessionKnown := s.sessions[connID]
s.sessionsMutex.RUnlock()
if sessionKnown && session == nil {
// Late packet for closed session
return nil
}
// ignore all Public Reset packets // ignore all Public Reset packets
if hdr.ResetFlag { if hdr.ResetFlag {
if ok { if sessionKnown {
var pr *wire.PublicReset var pr *wire.PublicReset
pr, err = wire.ParsePublicReset(r) pr, err = wire.ParsePublicReset(r)
if err != nil { if err != nil {
@ -264,10 +251,18 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
return nil return nil
} }
// If we don't have a session for this connection, and this packet cannot open a new connection, send a Public Reset
// 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)
return err
}
// a session is only created once the client sent a supported version // a session is only created once the client sent a supported version
// if we receive a packet for a connection that already has session, it's probably an old packet that was sent by the client before the version was negotiated // if we receive a packet for a connection that already has session, it's probably an old packet that was sent by the client before the version was negotiated
// it is safe to drop it // it is safe to drop it
if ok && hdr.VersionFlag && !protocol.IsSupportedVersion(s.config.Versions, hdr.Version) { if sessionKnown && hdr.VersionFlag && !protocol.IsSupportedVersion(s.config.Versions, hdr.Version) {
return nil return nil
} }
@ -289,7 +284,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
return err return err
} }
if !ok { if !sessionKnown {
version := hdr.Version version := hdr.Version
if !protocol.IsSupportedVersion(s.config.Versions, version) { if !protocol.IsSupportedVersion(s.config.Versions, version) {
return errors.New("Server BUG: negotiated version not supported") return errors.New("Server BUG: negotiated version not supported")

View file

@ -422,7 +422,7 @@ var _ = Describe("Server", func() {
Eventually(func() int { return conn.dataWritten.Len() }).ShouldNot(BeZero()) Eventually(func() int { return conn.dataWritten.Len() }).ShouldNot(BeZero())
Expect(conn.dataWrittenTo).To(Equal(udpAddr)) Expect(conn.dataWrittenTo).To(Equal(udpAddr))
r := bytes.NewReader(conn.dataWritten.Bytes()) r := bytes.NewReader(conn.dataWritten.Bytes())
packet, err := wire.ParseHeader(r, protocol.PerspectiveServer, protocol.VersionUnknown) packet, err := wire.ParseHeaderSentByServer(r, protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(packet.VersionFlag).To(BeTrue()) Expect(packet.VersionFlag).To(BeTrue())
Expect(packet.ConnectionID).To(Equal(protocol.ConnectionID(0x1337))) Expect(packet.ConnectionID).To(Equal(protocol.ConnectionID(0x1337)))
@ -455,7 +455,7 @@ var _ = Describe("Server", func() {
Eventually(func() int { return conn.dataWritten.Len() }).ShouldNot(BeZero()) Eventually(func() int { return conn.dataWritten.Len() }).ShouldNot(BeZero())
Expect(conn.dataWrittenTo).To(Equal(udpAddr)) Expect(conn.dataWrittenTo).To(Equal(udpAddr))
r := bytes.NewReader(conn.dataWritten.Bytes()) r := bytes.NewReader(conn.dataWritten.Bytes())
packet, err := wire.ParseHeader(r, protocol.PerspectiveServer, protocol.VersionUnknown) packet, err := wire.ParseHeaderSentByServer(r, protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(packet.Type).To(Equal(protocol.PacketTypeVersionNegotiation)) Expect(packet.Type).To(Equal(protocol.PacketTypeVersionNegotiation))
Expect(packet.ConnectionID).To(Equal(protocol.ConnectionID(0x1337))) Expect(packet.ConnectionID).To(Equal(protocol.ConnectionID(0x1337)))