more the PublicHeader to the wire package

This commit is contained in:
Marten Seemann 2017-08-29 23:45:38 +07:00
parent 88afad8722
commit 1794636220
16 changed files with 107 additions and 89 deletions

View file

@ -13,6 +13,7 @@ import (
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/wire"
)
type client struct {
@ -224,7 +225,7 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
rcvTime := time.Now()
r := bytes.NewReader(packet)
hdr, err := ParsePublicHeader(r, protocol.PerspectiveServer, c.version)
hdr, err := wire.ParsePublicHeader(r, protocol.PerspectiveServer, c.version)
if err != nil {
utils.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error())
// drop this packet if we can't parse the Public Header
@ -280,7 +281,7 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
})
}
func (c *client) handlePacketWithVersionFlag(hdr *PublicHeader) error {
func (c *client) handlePacketWithVersionFlag(hdr *wire.PublicHeader) error {
for _, v := range hdr.SupportedVersions {
if v == c.version {
// the version negotiation packet contains the version that we offered

View file

@ -9,6 +9,7 @@ import (
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/wire"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -228,7 +229,7 @@ var _ = Describe("Client", func() {
Context("version negotiation", func() {
It("recognizes that a packet without VersionFlag means that the server accepted the suggested version", func() {
ph := PublicHeader{
ph := wire.PublicHeader{
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
ConnectionID: 0x1337,
@ -262,7 +263,7 @@ var _ = Describe("Client", func() {
Expect(newVersion).ToNot(Equal(cl.version))
Expect(sess.packetCount).To(BeZero())
cl.connectionID = 0x1337
cl.handlePacket(nil, composeVersionNegotiation(0x1337, []protocol.VersionNumber{newVersion}))
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{newVersion}))
Expect(cl.version).To(Equal(newVersion))
Expect(cl.versionNegotiated).To(BeTrue())
// it swapped the sessions
@ -274,7 +275,7 @@ var _ = Describe("Client", func() {
})
It("errors if no matching version is found", func() {
cl.handlePacket(nil, composeVersionNegotiation(0x1337, []protocol.VersionNumber{1}))
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{1}))
Expect(cl.session.(*mockSession).closed).To(BeTrue())
Expect(cl.session.(*mockSession).closeReason).To(MatchError(qerr.InvalidVersion))
})
@ -283,13 +284,13 @@ var _ = Describe("Client", func() {
v := protocol.SupportedVersions[1]
Expect(v).ToNot(Equal(cl.version))
Expect(config.Versions).ToNot(ContainElement(v))
cl.handlePacket(nil, composeVersionNegotiation(0x1337, []protocol.VersionNumber{v}))
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{v}))
Expect(cl.session.(*mockSession).closed).To(BeTrue())
Expect(cl.session.(*mockSession).closeReason).To(MatchError(qerr.InvalidVersion))
})
It("changes to the version preferred by the quic.Config", func() {
cl.handlePacket(nil, composeVersionNegotiation(0x1337, []protocol.VersionNumber{config.Versions[2], config.Versions[1]}))
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{config.Versions[2], config.Versions[1]}))
Expect(cl.version).To(Equal(config.Versions[1]))
})
@ -297,14 +298,14 @@ var _ = Describe("Client", func() {
// if the version was not yet negotiated, handlePacket would return a VersionNegotiationMismatch error, see above test
cl.versionNegotiated = true
Expect(sess.packetCount).To(BeZero())
cl.handlePacket(nil, composeVersionNegotiation(0x1337, []protocol.VersionNumber{1}))
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{1}))
Expect(cl.versionNegotiated).To(BeTrue())
Expect(sess.packetCount).To(BeZero())
})
It("drops version negotiation packets that contain the offered version", func() {
ver := cl.version
cl.handlePacket(nil, composeVersionNegotiation(0x1337, []protocol.VersionNumber{ver}))
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{ver}))
Expect(cl.version).To(Equal(ver))
})
})
@ -351,7 +352,7 @@ var _ = Describe("Client", func() {
Context("handling packets", func() {
It("handles packets", func() {
ph := PublicHeader{
ph := wire.PublicHeader{
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
ConnectionID: 0x1337,

View file

@ -7,8 +7,8 @@ import (
"sync/atomic"
"time"
"github.com/lucas-clemente/quic-go"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/wire"
)
// Connection is a UDP connection
@ -165,7 +165,7 @@ func (p *QuicProxy) runProxy() error {
atomic.AddUint64(&conn.incomingPacketCounter, 1)
r := bytes.NewReader(raw)
hdr, err := quic.ParsePublicHeader(r, protocol.PerspectiveClient, protocol.VersionWhatever)
hdr, err := wire.ParsePublicHeader(r, protocol.PerspectiveClient, protocol.VersionWhatever)
if err != nil {
return err
}
@ -202,7 +202,7 @@ func (p *QuicProxy) runConnection(conn *connection) error {
// TODO: Switch back to using the public header once Chrome properly sets the type byte.
// r := bytes.NewReader(raw)
// , err := quic.ParsePublicHeader(r, protocol.PerspectiveServer)
// , err := wire.ParsePublicHeader(r, protocol.PerspectiveServer)
// if err != nil {
// return err
// }

View file

@ -9,8 +9,8 @@ import (
"fmt"
"github.com/lucas-clemente/quic-go"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/wire"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@ -22,7 +22,7 @@ var _ = Describe("QUIC Proxy", func() {
makePacket := func(p protocol.PacketNumber, payload []byte) []byte {
b := &bytes.Buffer{}
hdr := quic.PublicHeader{
hdr := wire.PublicHeader{
PacketNumber: p,
PacketNumberLen: protocol.PacketNumberLen6,
ConnectionID: 1337,

View file

@ -264,10 +264,10 @@ func (p *packetPacker) QueueControlFrame(frame wire.Frame) {
}
}
func (p *packetPacker) getPublicHeader(encLevel protocol.EncryptionLevel) *PublicHeader {
func (p *packetPacker) getPublicHeader(encLevel protocol.EncryptionLevel) *wire.PublicHeader {
pnum := p.packetNumberGenerator.Peek()
packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(pnum, p.leastUnacked)
publicHeader := &PublicHeader{
publicHeader := &wire.PublicHeader{
ConnectionID: p.connectionID,
PacketNumber: pnum,
PacketNumberLen: packetNumberLen,
@ -286,7 +286,7 @@ func (p *packetPacker) getPublicHeader(encLevel protocol.EncryptionLevel) *Publi
}
func (p *packetPacker) writeAndSealPacket(
publicHeader *PublicHeader,
publicHeader *wire.PublicHeader,
payloadFrames []wire.Frame,
sealer handshake.Sealer,
) ([]byte, error) {

View file

@ -238,7 +238,7 @@ var _ = Describe("Packet packer", func() {
p, err := packer.PackPacket()
Expect(err).ToNot(HaveOccurred())
Expect(p).ToNot(BeNil())
hdr, err := ParsePublicHeader(bytes.NewReader(p.raw), protocol.PerspectiveClient, packer.version)
hdr, err := wire.ParsePublicHeader(bytes.NewReader(p.raw), protocol.PerspectiveClient, packer.version)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.VersionNumber).To(Equal(packer.version))
@ -252,7 +252,7 @@ var _ = Describe("Packet packer", func() {
p, err := packer.PackPacket()
Expect(err).ToNot(HaveOccurred())
Expect(p).ToNot(BeNil())
hdr, err := ParsePublicHeader(bytes.NewReader(p.raw), protocol.PerspectiveClient, packer.version)
hdr, err := wire.ParsePublicHeader(bytes.NewReader(p.raw), protocol.PerspectiveClient, packer.version)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.VersionFlag).To(BeFalse())
})

View file

@ -24,7 +24,7 @@ type packetUnpacker struct {
aead quicAEAD
}
func (u *packetUnpacker) Unpack(publicHeaderBinary []byte, hdr *PublicHeader, data []byte) (*unpackedPacket, error) {
func (u *packetUnpacker) Unpack(publicHeaderBinary []byte, hdr *wire.PublicHeader, data []byte) (*unpackedPacket, error) {
buf := getPacketBuffer()
defer putPacketBuffer(buf)
decrypted, encryptionLevel, err := u.aead.Open(buf, data, hdr.PacketNumber, publicHeaderBinary)

View file

@ -31,14 +31,14 @@ var _ quicAEAD = &mockAEAD{}
var _ = Describe("Packet unpacker", func() {
var (
unpacker *packetUnpacker
hdr *PublicHeader
hdr *wire.PublicHeader
hdrBin []byte
data []byte
buf *bytes.Buffer
)
BeforeEach(func() {
hdr = &PublicHeader{
hdr = &wire.PublicHeader{
PacketNumber: 10,
PacketNumberLen: 1,
}

View file

@ -13,6 +13,7 @@ import (
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/wire"
)
// packetHandler handles packets
@ -212,7 +213,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
rcvTime := time.Now()
r := bytes.NewReader(packet)
connID, err := peekConnectionID(r, protocol.PerspectiveClient)
connID, err := wire.PeekConnectionID(r, protocol.PerspectiveClient)
if err != nil {
return qerr.Error(qerr.InvalidPacketHeader, err.Error())
}
@ -231,8 +232,8 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
version = session.GetVersion()
}
hdr, err := ParsePublicHeader(r, protocol.PerspectiveClient, version)
if err == errPacketWithUnknownVersion {
hdr, err := wire.ParsePublicHeader(r, protocol.PerspectiveClient, version)
if err == wire.ErrPacketWithUnknownVersion {
_, err = pconn.WriteTo(writePublicReset(connID, 0, 0), remoteAddr)
return err
}
@ -271,7 +272,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
return errors.New("dropping small packet with unknown version")
}
utils.Infof("Client offered version %d, sending VersionNegotiationPacket", hdr.VersionNumber)
_, err = pconn.WriteTo(composeVersionNegotiation(hdr.ConnectionID, s.config.Versions), remoteAddr)
_, err = pconn.WriteTo(wire.ComposeVersionNegotiation(hdr.ConnectionID, s.config.Versions), remoteAddr)
return err
}
@ -337,20 +338,3 @@ func (s *server) removeConnection(id protocol.ConnectionID) {
s.sessionsMutex.Unlock()
})
}
func composeVersionNegotiation(connectionID protocol.ConnectionID, versions []protocol.VersionNumber) []byte {
fullReply := &bytes.Buffer{}
responsePublicHeader := PublicHeader{
ConnectionID: connectionID,
PacketNumber: 1,
VersionFlag: true,
}
err := responsePublicHeader.Write(fullReply, protocol.VersionWhatever, protocol.PerspectiveServer)
if err != nil {
utils.Errorf("error composing version negotiation packet: %s", err.Error())
}
for _, v := range versions {
utils.LittleEndian.WriteUint32(fullReply, protocol.VersionNumberToTag(v))
}
return fullReply.Bytes()
}

View file

@ -14,6 +14,7 @@ import (
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/wire"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -128,14 +129,6 @@ var _ = Describe("Server", func() {
Expect(serv.Addr().String()).To(Equal("192.168.13.37:1234"))
})
It("composes version negotiation packets", func() {
expected := append(
[]byte{0x01 | 0x08, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
[]byte{'Q', '0', '9', '9'}...,
)
Expect(composeVersionNegotiation(1, []protocol.VersionNumber{99})).To(Equal(expected))
})
It("creates new sessions", func() {
err := serv.handlePacket(nil, nil, firstPacket)
Expect(err).ToNot(HaveOccurred())
@ -334,7 +327,7 @@ 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 := PublicHeader{
hdr := wire.PublicHeader{
VersionFlag: true,
ConnectionID: 0x1337,
PacketNumber: 1,
@ -402,7 +395,7 @@ var _ = Describe("Server", func() {
It("setups and responds with version negotiation", func() {
config.Versions = []protocol.VersionNumber{99}
b := &bytes.Buffer{}
hdr := PublicHeader{
hdr := wire.PublicHeader{
VersionFlag: true,
ConnectionID: 0x1337,
PacketNumber: 1,

View file

@ -20,12 +20,12 @@ import (
)
type unpacker interface {
Unpack(publicHeaderBinary []byte, hdr *PublicHeader, data []byte) (*unpackedPacket, error)
Unpack(publicHeaderBinary []byte, hdr *wire.PublicHeader, data []byte) (*unpackedPacket, error)
}
type receivedPacket struct {
remoteAddr net.Addr
publicHeader *PublicHeader
publicHeader *wire.PublicHeader
data []byte
rcvTime time.Time
}

View file

@ -61,7 +61,7 @@ type mockUnpacker struct {
unpackErr error
}
func (m *mockUnpacker) Unpack(publicHeaderBinary []byte, hdr *PublicHeader, data []byte) (*unpackedPacket, error) {
func (m *mockUnpacker) Unpack(publicHeaderBinary []byte, hdr *wire.PublicHeader, data []byte) (*unpackedPacket, error) {
if m.unpackErr != nil {
return nil, m.unpackErr
}
@ -847,11 +847,11 @@ var _ = Describe("Session", func() {
})
Context("receiving packets", func() {
var hdr *PublicHeader
var hdr *wire.PublicHeader
BeforeEach(func() {
sess.unpacker = &mockUnpacker{}
hdr = &PublicHeader{PacketNumberLen: protocol.PacketNumberLen6}
hdr = &wire.PublicHeader{PacketNumberLen: protocol.PacketNumberLen6}
})
It("sets the {last,largest}RcvdPacketNumber", func() {
@ -903,7 +903,7 @@ var _ = Describe("Session", func() {
Expect(sess.conn.(*mockConnection).remoteAddr).ToNot(Equal(remoteIP))
p := receivedPacket{
remoteAddr: remoteIP,
publicHeader: &PublicHeader{PacketNumber: 1337},
publicHeader: &wire.PublicHeader{PacketNumber: 1337},
}
err := sess.handlePacketImpl(&p)
Expect(err).ToNot(HaveOccurred())
@ -919,7 +919,7 @@ var _ = Describe("Session", func() {
sess.unpacker.(*packetUnpacker).aead = &mockAEAD{}
p := receivedPacket{
remoteAddr: attackerIP,
publicHeader: &PublicHeader{PacketNumber: 1337},
publicHeader: &wire.PublicHeader{PacketNumber: 1337},
}
err := sess.handlePacketImpl(&p)
quicErr := err.(*qerr.QuicError)
@ -933,7 +933,7 @@ var _ = Describe("Session", func() {
Expect(sess.conn.(*mockConnection).remoteAddr).ToNot(Equal(remoteIP))
p := receivedPacket{
remoteAddr: remoteIP,
publicHeader: &PublicHeader{PacketNumber: 1337},
publicHeader: &wire.PublicHeader{PacketNumber: 1337},
}
sess.unpacker.(*mockUnpacker).unpackErr = testErr
err := sess.handlePacketImpl(&p)
@ -1347,7 +1347,7 @@ var _ = Describe("Session", func() {
// this completely fills up the undecryptable packets queue and triggers the public reset timer
sendUndecryptablePackets := func() {
for i := 0; i < protocol.MaxUndecryptablePackets+1; i++ {
hdr := &PublicHeader{
hdr := &wire.PublicHeader{
PacketNumber: protocol.PacketNumber(i + 1),
}
sess.handlePacket(&receivedPacket{
@ -1420,7 +1420,7 @@ var _ = Describe("Session", func() {
It("unqueues undecryptable packets for later decryption", func() {
sess.undecryptablePackets = []*receivedPacket{{
publicHeader: &PublicHeader{PacketNumber: protocol.PacketNumber(42)},
publicHeader: &wire.PublicHeader{PacketNumber: protocol.PacketNumber(42)},
}}
Expect(sess.receivedPackets).NotTo(Receive())
sess.tryDecryptingQueuedPackets()
@ -1722,10 +1722,10 @@ var _ = Describe("Client Session", func() {
})
Context("receiving packets", func() {
var hdr *PublicHeader
var hdr *wire.PublicHeader
BeforeEach(func() {
hdr = &PublicHeader{PacketNumberLen: protocol.PacketNumberLen6}
hdr = &wire.PublicHeader{PacketNumberLen: protocol.PacketNumberLen6}
sess.unpacker = &mockUnpacker{}
})

View file

@ -1,4 +1,4 @@
package quic
package wire
import (
"bytes"
@ -11,13 +11,13 @@ import (
)
var (
errPacketNumberLenNotSet = errors.New("PublicHeader: PacketNumberLen not set")
// 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")
errReceivedTruncatedConnectionID = qerr.Error(qerr.InvalidPacketHeader, "receiving packets with truncated ConnectionID is not supported")
errInvalidConnectionID = qerr.Error(qerr.InvalidPacketHeader, "connection ID cannot be 0")
errGetLengthNotForVersionNegotiation = errors.New("PublicHeader: GetLength cannot be called for VersionNegotiation packets")
// 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")
)
// The PublicHeader of a QUIC packet. Warning: This struct should not be considered stable and will change soon.
@ -93,10 +93,6 @@ func (h *PublicHeader) Write(b *bytes.Buffer, version protocol.VersionNumber, pe
return nil
}
if h.PacketNumberLen != protocol.PacketNumberLen1 && h.PacketNumberLen != protocol.PacketNumberLen2 && h.PacketNumberLen != protocol.PacketNumberLen4 && h.PacketNumberLen != protocol.PacketNumberLen6 {
return errPacketNumberLenNotSet
}
switch h.PacketNumberLen {
case protocol.PacketNumberLen1:
b.WriteByte(uint8(h.PacketNumber))
@ -107,15 +103,15 @@ func (h *PublicHeader) Write(b *bytes.Buffer, version protocol.VersionNumber, pe
case protocol.PacketNumberLen6:
utils.GetByteOrder(version).WriteUint48(b, uint64(h.PacketNumber)&(1<<48-1))
default:
return errPacketNumberLenNotSet
return errors.New("PublicHeader: PacketNumberLen not set")
}
return nil
}
// peekConnectionID parses the connection ID from a QUIC packet's public header.
// PeekConnectionID parses the connection ID from a QUIC packet's public header.
// If no error occurs, it restores the read position in the bytes.Reader.
func peekConnectionID(b *bytes.Reader, packetSentBy protocol.Perspective) (protocol.ConnectionID, error) {
func PeekConnectionID(b *bytes.Reader, packetSentBy protocol.Perspective) (protocol.ConnectionID, error) {
var connectionID protocol.ConnectionID
publicFlagByte, err := b.ReadByte()
if err != nil {
@ -156,7 +152,7 @@ func ParsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective, versi
header.ResetFlag = publicFlagByte&0x02 > 0
header.VersionFlag = publicFlagByte&0x01 > 0
if version == protocol.VersionUnknown && !(header.VersionFlag || header.ResetFlag) {
return nil, errPacketWithUnknownVersion
return nil, ErrPacketWithUnknownVersion
}
// TODO: activate this check once Chrome sends the correct value

View file

@ -1,4 +1,4 @@
package quic
package wire
import (
"bytes"
@ -15,14 +15,14 @@ var _ = Describe("Public Header", func() {
Context("parsing the connection ID", func() {
It("does not accept truncated connection ID as a server", func() {
b := bytes.NewReader([]byte{0x00, 0x01})
_, err := peekConnectionID(b, protocol.PerspectiveClient)
_, err := PeekConnectionID(b, protocol.PerspectiveClient)
Expect(err).To(MatchError(errReceivedTruncatedConnectionID))
})
It("gets the connection ID", func() {
b := bytes.NewReader([]byte{0x09, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c, 0x51, 0x30, 0x33, 0x34, 0x01})
len := b.Len()
connID, err := peekConnectionID(b, protocol.PerspectiveClient)
connID, err := PeekConnectionID(b, protocol.PerspectiveClient)
Expect(err).ToNot(HaveOccurred())
Expect(connID).To(Equal(protocol.ConnectionID(0x4cfa9f9b668619f6)))
Expect(b.Len()).To(Equal(len))
@ -30,20 +30,20 @@ var _ = Describe("Public Header", func() {
It("errors if the Public Header is too short", func() {
b := bytes.NewReader([]byte{0x09, 0xf6, 0x19, 0x86, 0x66, 0x9b})
_, err := peekConnectionID(b, protocol.PerspectiveClient)
_, err := PeekConnectionID(b, protocol.PerspectiveClient)
Expect(err).To(HaveOccurred())
})
It("errors if the Public Header is empty", func() {
b := bytes.NewReader([]byte{})
_, err := peekConnectionID(b, protocol.PerspectiveClient)
_, err := PeekConnectionID(b, protocol.PerspectiveClient)
Expect(err).To(HaveOccurred())
})
It("accepts a truncated connection ID as a client", func() {
b := bytes.NewReader([]byte{0x00, 0x01})
len := b.Len()
connID, err := peekConnectionID(b, protocol.PerspectiveServer)
connID, err := PeekConnectionID(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(connID).To(BeZero())
Expect(b.Len()).To(Equal(len))
@ -116,7 +116,7 @@ var _ = Describe("Public Header", func() {
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))
Expect(err).To(MatchError(ErrPacketWithUnknownVersion))
})
PIt("rejects diversification nonces sent by the client", func() {
@ -136,7 +136,7 @@ var _ = Describe("Public Header", func() {
}
It("parses version negotiation packets sent by the server", func() {
b := bytes.NewReader(composeVersionNegotiation(0x1337, protocol.SupportedVersions))
b := bytes.NewReader(ComposeVersionNegotiation(0x1337, protocol.SupportedVersions))
hdr, err := ParsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.VersionFlag).To(BeTrue())
@ -169,7 +169,7 @@ var _ = Describe("Public Header", func() {
})
It("errors on invalid version tags", func() {
data := composeVersionNegotiation(0x1337, protocol.SupportedVersions)
data := ComposeVersionNegotiation(0x1337, protocol.SupportedVersions)
data = append(data, []byte{0x13, 0x37}...)
b := bytes.NewReader(data)
_, err := ParsePublicHeader(b, protocol.PerspectiveServer, protocol.VersionUnknown)
@ -300,7 +300,7 @@ var _ = Describe("Public Header", func() {
}
b := &bytes.Buffer{}
err := hdr.Write(b, protocol.VersionWhatever, protocol.PerspectiveServer)
Expect(err).To(MatchError(errPacketNumberLenNotSet))
Expect(err).To(MatchError("PublicHeader: PacketNumberLen not set"))
})
It("truncates the connection ID", func() {
@ -526,7 +526,7 @@ var _ = Describe("Public Header", func() {
PacketNumber: 0xDECAFBAD,
}
err := hdr.Write(b, protocol.VersionWhatever, protocol.PerspectiveServer)
Expect(err).To(MatchError(errPacketNumberLenNotSet))
Expect(err).To(MatchError("PublicHeader: PacketNumberLen not set"))
})
Context("in little endian", func() {

View file

@ -0,0 +1,26 @@
package wire
import (
"bytes"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
)
// ComposeVersionNegotiation composes a Version Negotiation Packet
func ComposeVersionNegotiation(connectionID protocol.ConnectionID, versions []protocol.VersionNumber) []byte {
fullReply := &bytes.Buffer{}
responsePublicHeader := PublicHeader{
ConnectionID: connectionID,
PacketNumber: 1,
VersionFlag: true,
}
err := responsePublicHeader.Write(fullReply, protocol.VersionWhatever, protocol.PerspectiveServer)
if err != nil {
utils.Errorf("error composing version negotiation packet: %s", err.Error())
}
for _, v := range versions {
utils.LittleEndian.WriteUint32(fullReply, protocol.VersionNumberToTag(v))
}
return fullReply.Bytes()
}

View file

@ -0,0 +1,17 @@
package wire
import (
"github.com/lucas-clemente/quic-go/protocol"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Version Negotiation Packet", func() {
It("composes version negotiation packets", func() {
expected := append(
[]byte{0x01 | 0x08, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
[]byte{'Q', '0', '9', '9'}...,
)
Expect(ComposeVersionNegotiation(1, []protocol.VersionNumber{99})).To(Equal(expected))
})
})