diff --git a/internal/wire/public_header.go b/internal/wire/public_header.go index 593ac771..77bd8f52 100644 --- a/internal/wire/public_header.go +++ b/internal/wire/public_header.go @@ -20,6 +20,9 @@ var ( // writePublicHeader writes a Public Header. func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _ protocol.VersionNumber) error { + if h.VersionFlag && pers == protocol.PerspectiveServer { + return errors.New("PublicHeader: Writing of Version Negotiation Packets not supported") + } if h.VersionFlag && h.ResetFlag { return errResetAndVersionFlagSet } diff --git a/internal/wire/public_header_test.go b/internal/wire/public_header_test.go index 21f563cf..762b3b61 100644 --- a/internal/wire/public_header_test.go +++ b/internal/wire/public_header_test.go @@ -242,47 +242,40 @@ var _ = Describe("Public Header", func() { VersionFlag: true, ResetFlag: true, } - err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever) + err := hdr.writePublicHeader(b, protocol.PerspectiveClient, protocol.VersionWhatever) Expect(err).To(MatchError(errResetAndVersionFlagSet)) }) - Context("Version Negotiation packets", func() { - It("sets the Version Flag for packets sent as a server", func() { - b := &bytes.Buffer{} - hdr := Header{ - VersionFlag: true, - ConnectionID: 0x4cfa9f9b668619f6, - PacketNumber: 2, - PacketNumberLen: protocol.PacketNumberLen6, - } - err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - // must be the first assertion - Expect(b.Len()).To(Equal(1 + 8)) // 1 FlagByte + 8 ConnectionID - firstByte, _ := b.ReadByte() - Expect(firstByte & 0x01).To(Equal(uint8(1))) - Expect(firstByte & 0x30).To(BeZero()) // no packet number present - }) + It("doesn't write Version Negotiation Packets", func() { + b := &bytes.Buffer{} + hdr := Header{ + VersionFlag: true, + ConnectionID: 0x4cfa9f9b668619f6, + 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")) + }) - It("sets the Version Flag for packets sent as a client, and adds a packet number", func() { - b := &bytes.Buffer{} - hdr := Header{ - VersionFlag: true, - Version: protocol.Version39, - ConnectionID: 0x4cfa9f9b668619f6, - PacketNumber: 0x42, - PacketNumberLen: protocol.PacketNumberLen1, - } - err := hdr.writePublicHeader(b, protocol.PerspectiveClient, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - // must be the first assertion - Expect(b.Len()).To(Equal(1 + 8 + 4 + 1)) // 1 FlagByte + 8 ConnectionID + 4 version number + 1 PacketNumber - firstByte, _ := b.ReadByte() - Expect(firstByte & 0x01).To(Equal(uint8(1))) - Expect(firstByte & 0x30).To(Equal(uint8(0x0))) - Expect(string(b.Bytes()[8:12])).To(Equal("Q039")) - Expect(b.Bytes()[12:13]).To(Equal([]byte{0x42})) - }) + It("writes packets with Version Flag, as a client", func() { + b := &bytes.Buffer{} + hdr := Header{ + VersionFlag: true, + Version: protocol.Version39, + ConnectionID: 0x4cfa9f9b668619f6, + PacketNumber: 0x42, + PacketNumberLen: protocol.PacketNumberLen1, + } + err := hdr.writePublicHeader(b, protocol.PerspectiveClient, protocol.VersionWhatever) + Expect(err).ToNot(HaveOccurred()) + // must be the first assertion + Expect(b.Len()).To(Equal(1 + 8 + 4 + 1)) // 1 FlagByte + 8 ConnectionID + 4 version number + 1 PacketNumber + firstByte, _ := b.ReadByte() + Expect(firstByte & 0x01).To(Equal(uint8(1))) + Expect(firstByte & 0x30).To(Equal(uint8(0x0))) + Expect(string(b.Bytes()[8:12])).To(Equal("Q039")) + Expect(b.Bytes()[12:13]).To(Equal([]byte{0x42})) }) Context("PublicReset packets", func() { diff --git a/internal/wire/version_negotiation.go b/internal/wire/version_negotiation.go index dea90ee1..cf72fc2e 100644 --- a/internal/wire/version_negotiation.go +++ b/internal/wire/version_negotiation.go @@ -10,17 +10,9 @@ import ( // ComposeGQUICVersionNegotiation composes a Version Negotiation Packet for gQUIC func ComposeGQUICVersionNegotiation(connID protocol.ConnectionID, versions []protocol.VersionNumber) []byte { - buf := &bytes.Buffer{} - ph := Header{ - ConnectionID: connID, - PacketNumber: 1, - VersionFlag: true, - IsVersionNegotiation: true, - } - if err := ph.writePublicHeader(buf, protocol.PerspectiveServer, protocol.VersionWhatever); err != nil { - utils.Errorf("error composing version negotiation packet: %s", err.Error()) - return nil - } + buf := bytes.NewBuffer(make([]byte, 0, 1+8+len(versions)*4)) + buf.Write([]byte{0x1 | 0x8}) // type byte + utils.BigEndian.WriteUint64(buf, uint64(connID)) for _, v := range versions { utils.BigEndian.WriteUint32(buf, uint32(v)) }