change the type of Connection ID to byte slice

This commit is contained in:
Marten Seemann 2018-03-16 13:29:47 +01:00
parent af8971d8c9
commit 1a035a265c
28 changed files with 258 additions and 189 deletions

View file

@ -308,7 +308,7 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
defer c.mutex.Unlock()
// reject packets with the wrong connection ID
if !hdr.OmitConnectionID && hdr.ConnectionID != c.connectionID {
if !hdr.OmitConnectionID && !hdr.ConnectionID.Equal(c.connectionID) {
return
}
@ -316,7 +316,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 != c.connectionID {
if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || !hdr.ConnectionID.Equal(c.connectionID) {
c.logger.Infof("Received a spoofed Public Reset. Ignoring.")
return
}

View file

@ -25,6 +25,7 @@ var _ = Describe("Client", func() {
sess *mockSession
packetConn *mockPacketConn
addr net.Addr
connID protocol.ConnectionID
originalClientSessConstructor func(conn connection, hostname string, v protocol.VersionNumber, connectionID protocol.ConnectionID, tlsConf *tls.Config, config *Config, initialVersion protocol.VersionNumber, negotiatedVersions []protocol.VersionNumber, logger utils.Logger) (packetHandler, error)
)
@ -42,16 +43,17 @@ var _ = Describe("Client", func() {
}
BeforeEach(func() {
connID = protocol.ConnectionID{0, 0, 0, 0, 0, 0, 0x13, 0x37}
originalClientSessConstructor = newClientSession
Eventually(areSessionsRunning).Should(BeFalse())
msess, _ := newMockSession(nil, 0, 0, nil, nil, nil, nil)
msess, _ := newMockSession(nil, 0, connID, nil, nil, nil, nil)
sess = msess.(*mockSession)
addr = &net.UDPAddr{IP: net.IPv4(192, 168, 100, 200), Port: 1337}
packetConn = newMockPacketConn()
packetConn.addr = &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1234}
packetConn.dataReadFrom = addr
cl = &client{
connectionID: 0x1337,
connectionID: connID,
session: sess,
version: protocol.SupportedVersions[0],
conn: &conn{pconn: packetConn, currentAddr: addr},
@ -293,7 +295,7 @@ var _ = Describe("Client", func() {
ph := wire.Header{
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
ConnectionID: 0x1337,
ConnectionID: connID,
}
b := &bytes.Buffer{}
err := ph.Write(b, protocol.PerspectiveServer, protocol.VersionWhatever)
@ -388,15 +390,15 @@ var _ = Describe("Client", func() {
go cl.dial()
Eventually(func() uint32 { return atomic.LoadUint32(&sessionCounter) }).Should(BeEquivalentTo(1))
cl.config = &Config{Versions: []protocol.VersionNumber{77, 78}}
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(0x1337, []protocol.VersionNumber{77}))
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{77}))
Eventually(func() uint32 { return atomic.LoadUint32(&sessionCounter) }).Should(BeEquivalentTo(2))
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(0x1337, []protocol.VersionNumber{78}))
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{78}))
Consistently(func() uint32 { return atomic.LoadUint32(&sessionCounter) }).Should(BeEquivalentTo(2))
})
It("errors if no matching version is found", func() {
cl.config = &Config{Versions: protocol.SupportedVersions}
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(0x1337, []protocol.VersionNumber{1}))
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{1}))
Expect(cl.session.(*mockSession).closed).To(BeTrue())
Expect(cl.session.(*mockSession).closeReason).To(MatchError(qerr.InvalidVersion))
})
@ -405,7 +407,7 @@ var _ = Describe("Client", func() {
v := protocol.VersionNumber(1234)
Expect(v).ToNot(Equal(cl.version))
cl.config = &Config{Versions: protocol.SupportedVersions}
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(0x1337, []protocol.VersionNumber{v}))
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{v}))
Expect(cl.session.(*mockSession).closed).To(BeTrue())
Expect(cl.session.(*mockSession).closeReason).To(MatchError(qerr.InvalidVersion))
})
@ -413,7 +415,7 @@ var _ = Describe("Client", func() {
It("changes to the version preferred by the quic.Config", func() {
config := &Config{Versions: []protocol.VersionNumber{1234, 4321}}
cl.config = config
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(0x1337, []protocol.VersionNumber{4321, 1234}))
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{4321, 1234}))
Expect(cl.version).To(Equal(protocol.VersionNumber(1234)))
})
@ -421,14 +423,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, wire.ComposeGQUICVersionNegotiation(0x1337, []protocol.VersionNumber{1}))
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []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, wire.ComposeGQUICVersionNegotiation(0x1337, []protocol.VersionNumber{ver}))
cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{ver}))
Expect(cl.version).To(Equal(ver))
})
})
@ -455,8 +457,10 @@ var _ = Describe("Client", func() {
It("ignores packets with the wrong connection ID", func() {
buf := &bytes.Buffer{}
connID2 := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7}
Expect(connID).ToNot(Equal(connID2))
(&wire.Header{
ConnectionID: cl.connectionID + 1,
ConnectionID: connID2,
PacketNumber: 1,
PacketNumberLen: 1,
}).Write(buf, protocol.PerspectiveServer, protocol.VersionWhatever)
@ -587,7 +591,7 @@ var _ = Describe("Client", func() {
ph := wire.Header{
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
ConnectionID: 0x1337,
ConnectionID: connID,
}
b := &bytes.Buffer{}
err := ph.Write(b, protocol.PerspectiveServer, cl.version)
@ -625,7 +629,9 @@ var _ = Describe("Client", func() {
})
It("ignores Public Resets with the wrong connection ID", func() {
cl.handlePacket(addr, wire.WritePublicReset(cl.connectionID+1, 1, 0))
connID2 := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7}
Expect(connID).ToNot(Equal(connID2))
cl.handlePacket(addr, wire.WritePublicReset(connID2, 1, 0))
Expect(cl.session.(*mockSession).closed).To(BeFalse())
Expect(cl.session.(*mockSession).closedRemote).To(BeFalse())
})

View file

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

View file

@ -6,7 +6,6 @@ import (
"io"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
"golang.org/x/crypto/hkdf"
)
@ -42,7 +41,7 @@ func deriveKeys(forwardSecure bool, sharedSecret, nonces []byte, connID protocol
} else {
info.Write([]byte("QUIC key expansion\x00"))
}
utils.BigEndian.WriteUint64(&info, uint64(connID))
info.Write(connID)
info.Write(chlo)
info.Write(scfg)
info.Write(cert)

View file

@ -92,7 +92,7 @@ var _ = Describe("QUIC Crypto Key Derivation", func() {
false,
[]byte("0123456789012345678901"),
[]byte("nonce"),
protocol.ConnectionID(0x2a00000000000000), // this was 42 before the connection ID was changed to big endian
protocol.ConnectionID([]byte{42, 0, 0, 0, 0, 0, 0, 0}),
[]byte("chlo"),
[]byte("scfg"),
[]byte("cert"),
@ -111,7 +111,7 @@ var _ = Describe("QUIC Crypto Key Derivation", func() {
false,
[]byte("0123456789012345678901"),
[]byte("nonce"),
protocol.ConnectionID(42),
protocol.ConnectionID([]byte{42, 0, 0, 0, 0, 0, 0, 0}),
[]byte("chlo"),
[]byte("scfg"),
[]byte("cert"),
@ -123,7 +123,7 @@ var _ = Describe("QUIC Crypto Key Derivation", func() {
false,
[]byte("0123456789012345678901"),
[]byte("nonce"),
protocol.ConnectionID(42),
protocol.ConnectionID([]byte{42, 0, 0, 0, 0, 0, 0, 0}),
[]byte("chlo"),
[]byte("scfg"),
[]byte("cert"),
@ -142,7 +142,7 @@ var _ = Describe("QUIC Crypto Key Derivation", func() {
false,
[]byte("0123456789012345678901"),
[]byte("nonce"),
protocol.ConnectionID(0x2a00000000000000), // this was 42 before the connection ID was changed to big endian
protocol.ConnectionID([]byte{42, 0, 0, 0, 0, 0, 0, 0}),
[]byte("chlo"),
[]byte("scfg"),
[]byte("cert"),
@ -161,7 +161,7 @@ var _ = Describe("QUIC Crypto Key Derivation", func() {
true,
[]byte("0123456789012345678901"),
[]byte("nonce"),
protocol.ConnectionID(0x2a00000000000000), // this was 42 before the connection ID was changed to big endian
protocol.ConnectionID([]byte{42, 0, 0, 0, 0, 0, 0, 0}),
[]byte("chlo"),
[]byte("scfg"),
[]byte("cert"),
@ -180,7 +180,7 @@ var _ = Describe("QUIC Crypto Key Derivation", func() {
true,
[]byte("0123456789012345678901"),
[]byte("nonce"),
protocol.ConnectionID(0x2a00000000000000), // this was 42 before the connection ID was changed to big endian
protocol.ConnectionID([]byte{42, 0, 0, 0, 0, 0, 0, 0}),
[]byte("chlo"),
[]byte("scfg"),
[]byte("cert"),

View file

@ -2,7 +2,6 @@ package crypto
import (
"crypto"
"encoding/binary"
"github.com/bifurcation/mint"
"github.com/lucas-clemente/quic-go/internal/protocol"
@ -28,9 +27,7 @@ func newNullAEADAESGCM(connectionID protocol.ConnectionID, pers protocol.Perspec
return NewAEADAESGCM(otherKey, myKey, otherIV, myIV)
}
func computeSecrets(connectionID protocol.ConnectionID) (clientSecret, serverSecret []byte) {
connID := make([]byte, 8)
binary.BigEndian.PutUint64(connID, uint64(connectionID))
func computeSecrets(connID protocol.ConnectionID) (clientSecret, serverSecret []byte) {
handshakeSecret := mint.HkdfExtract(crypto.SHA256, quicVersion1Salt, connID)
clientSecret = qhkdfExpand(handshakeSecret, "client hs", crypto.SHA256.Size())
serverSecret = qhkdfExpand(handshakeSecret, "server hs", crypto.SHA256.Size())

View file

@ -9,7 +9,7 @@ import (
var _ = Describe("NullAEAD using AES-GCM", func() {
// values taken from https://github.com/quicwg/base-drafts/wiki/Test-Vector-for-the-Clear-Text-AEAD-key-derivation
Context("using the test vector from the QUIC WG Wiki", func() {
connID := protocol.ConnectionID(0x8394c8f03e515708)
connID := protocol.ConnectionID([]byte{0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08})
It("computes the secrets", func() {
clientSecret, serverSecret := computeSecrets(connID)
@ -55,7 +55,7 @@ var _ = Describe("NullAEAD using AES-GCM", func() {
})
It("seals and opens", func() {
connectionID := protocol.ConnectionID(0x1234567890)
connectionID := protocol.ConnectionID([]byte{0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef})
clientAEAD, err := newNullAEADAESGCM(connectionID, protocol.PerspectiveClient)
Expect(err).ToNot(HaveOccurred())
serverAEAD, err := newNullAEADAESGCM(connectionID, protocol.PerspectiveServer)
@ -72,9 +72,11 @@ var _ = Describe("NullAEAD using AES-GCM", func() {
})
It("doesn't work if initialized with different connection IDs", func() {
clientAEAD, err := newNullAEADAESGCM(1, protocol.PerspectiveClient)
c1 := protocol.ConnectionID([]byte{0, 0, 0, 0, 0, 0, 0, 1})
c2 := protocol.ConnectionID([]byte{0, 0, 0, 0, 0, 0, 0, 2})
clientAEAD, err := newNullAEADAESGCM(c1, protocol.PerspectiveClient)
Expect(err).ToNot(HaveOccurred())
serverAEAD, err := newNullAEADAESGCM(2, protocol.PerspectiveServer)
serverAEAD, err := newNullAEADAESGCM(c2, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
clientMessage := clientAEAD.Seal(nil, []byte("foobar"), 42, []byte("aad"))

View file

@ -8,7 +8,7 @@ import (
var _ = Describe("NullAEAD", func() {
It("selects the right FVN variant", func() {
connID := protocol.ConnectionID(0x42)
connID := protocol.ConnectionID([]byte{0x42, 0, 0, 0, 0, 0, 0, 0})
Expect(NewNullAEAD(protocol.PerspectiveClient, connID, protocol.Version39)).To(Equal(&nullAEADFNV128a{
perspective: protocol.PerspectiveClient,
}))

View file

@ -123,7 +123,7 @@ var _ = Describe("Client Crypto Setup", func() {
csInt, dnc, err := NewCryptoSetupClient(
stream,
"hostname",
0,
protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
version,
nil,
&TransportParameters{IdleTimeout: protocol.DefaultIdleTimeout},

View file

@ -161,7 +161,7 @@ var _ = Describe("Server Crypto Setup", func() {
supportedVersions = []protocol.VersionNumber{version, 98, 99}
csInt, err := NewCryptoSetup(
stream,
protocol.ConnectionID(42),
protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
remoteAddr,
version,
make([]byte, 32), // div nonce

View file

@ -200,7 +200,7 @@ var _ = Describe("TLS Crypto Setup, for the client", func() {
handshakeEvent = make(chan struct{})
csInt, err := NewCryptoSetupTLSClient(
nil,
0,
protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
"quic.clemente.io",
handshakeEvent,
nil, // mintTLS

View file

@ -1,19 +1,23 @@
package protocol
import (
"bytes"
"crypto/rand"
"encoding/binary"
)
// A ConnectionID in QUIC
type ConnectionID uint64
type ConnectionID []byte
// GenerateConnectionID generates a connection ID using cryptographic random
func GenerateConnectionID() (ConnectionID, error) {
b := make([]byte, 8)
_, err := rand.Read(b)
if err != nil {
return 0, err
if _, err := rand.Read(b); err != nil {
return nil, err
}
return ConnectionID(binary.LittleEndian.Uint64(b)), nil
return ConnectionID(b), nil
}
// Equal says if two connection IDs are equal
func (c ConnectionID) Equal(other ConnectionID) bool {
return bytes.Equal(c, other)
}

View file

@ -14,4 +14,13 @@ var _ = Describe("Connection ID generation", func() {
Expect(err).ToNot(HaveOccurred())
Expect(c1).ToNot(Equal(c2))
})
It("says if connection IDs are equal", func() {
c1 := ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
c2 := ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
Expect(c1.Equal(c1)).To(BeTrue())
Expect(c2.Equal(c2)).To(BeTrue())
Expect(c1.Equal(c2)).To(BeFalse())
Expect(c2.Equal(c1)).To(BeFalse())
})
})

View file

@ -24,6 +24,7 @@ var _ = Describe("Header", func() {
// 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,
@ -40,6 +41,7 @@ var _ = Describe("Header", 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,
@ -58,6 +60,7 @@ var _ = Describe("Header", func() {
buf := &bytes.Buffer{}
err := (&Header{
IsLongHeader: false,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 0x42,
}).writeHeader(buf)
@ -68,26 +71,29 @@ var _ = Describe("Header", func() {
})
It("parses a gQUIC Public Header, when the version is not known", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
buf := &bytes.Buffer{}
err := (&Header{
VersionFlag: true,
Version: versionPublicHeader,
ConnectionID: 0x42,
ConnectionID: 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.PacketNumber).To(Equal(protocol.PacketNumber(0x1337)))
Expect(hdr.Version).To(Equal(versionPublicHeader))
Expect(hdr.isPublicHeader).To(BeTrue())
})
It("parses a gQUIC Public Header, when the version is known", func() {
connID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
buf := &bytes.Buffer{}
err := (&Header{
ConnectionID: 0x42,
ConnectionID: connID,
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
DiversificationNonce: bytes.Repeat([]byte{'f'}, 32),
@ -95,6 +101,7 @@ 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.PacketNumber).To(Equal(protocol.PacketNumber(0x1337)))
Expect(hdr.DiversificationNonce).To(HaveLen(32))
Expect(hdr.isPublicHeader).To(BeTrue())
@ -105,7 +112,7 @@ var _ = Describe("Header", func() {
err := (&Header{
VersionFlag: true,
Version: versionPublicHeader,
ConnectionID: 0x42,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
}).writePublicHeader(buf, protocol.PerspectiveClient, versionPublicHeader)
@ -122,12 +129,13 @@ var _ = Describe("Header", func() {
})
It("parses a gQUIC Version Negotiation Packet", func() {
connID := protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad, 0xde, 0xca, 0xfb, 0xad}
versions := []protocol.VersionNumber{0x13, 0x37}
data := ComposeGQUICVersionNegotiation(0x42, versions)
data := ComposeGQUICVersionNegotiation(connID, 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.ConnectionID).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))
@ -135,13 +143,14 @@ 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}
versions := []protocol.VersionNumber{0x13, 0x37}
data := ComposeVersionNegotiation(0x42, versions)
data := ComposeVersionNegotiation(connID, versions)
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(protocol.ConnectionID(0x42)))
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.Version).To(BeZero())
// in addition to the versions, the supported versions might contain a reserved version number
for _, version := range versions {
@ -154,7 +163,7 @@ var _ = Describe("Header", func() {
It("writes a gQUIC Public Header", func() {
buf := &bytes.Buffer{}
hdr := &Header{
ConnectionID: 0x1337,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
}
@ -168,7 +177,7 @@ var _ = Describe("Header", func() {
It("writes a IETF draft header", func() {
buf := &bytes.Buffer{}
hdr := &Header{
ConnectionID: 0x1337,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
KeyPhase: 1,
@ -185,7 +194,7 @@ var _ = Describe("Header", func() {
It("get the length of a gQUIC Public Header", func() {
buf := &bytes.Buffer{}
hdr := &Header{
ConnectionID: 0x1337,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
DiversificationNonce: bytes.Repeat([]byte{'f'}, 32),
@ -206,7 +215,7 @@ var _ = Describe("Header", func() {
buf := &bytes.Buffer{}
hdr := &Header{
IsLongHeader: true,
ConnectionID: 0x1337,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen2,
KeyPhase: 1,
@ -244,6 +253,7 @@ 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},
}).Log(logger)
Expect(buf.String()).To(ContainSubstring("Long Header"))
})
@ -251,6 +261,7 @@ var _ = Describe("Header", func() {
It("logs a Public Header", func() {
(&Header{
isPublicHeader: true,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
}).Log(logger)
Expect(buf.String()).To(ContainSubstring("Public Header"))
})

View file

@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
"io"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
@ -24,8 +25,11 @@ 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, err := utils.BigEndian.ReadUint64(b)
if err != nil {
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)
@ -33,7 +37,7 @@ func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte
return nil, err
}
h := &Header{
ConnectionID: protocol.ConnectionID(connID),
ConnectionID: connID,
Version: protocol.VersionNumber(v),
}
if v == 0 { // version negotiation packet
@ -73,11 +77,12 @@ func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte
func parseShortHeader(b *bytes.Reader, typeByte byte) (*Header, error) {
omitConnID := typeByte&0x40 > 0
var connID uint64
connID := make(protocol.ConnectionID, 8)
if !omitConnID {
var err error
connID, err = utils.BigEndian.ReadUint64(b)
if err != nil {
if _, err := io.ReadFull(b, connID); err != nil {
if err == io.ErrUnexpectedEOF {
err = io.EOF
}
return nil, err
}
}
@ -103,7 +108,7 @@ func parseShortHeader(b *bytes.Reader, typeByte byte) (*Header, error) {
return &Header{
KeyPhase: int(typeByte&0x20) >> 5,
OmitConnectionID: omitConnID,
ConnectionID: protocol.ConnectionID(connID),
ConnectionID: connID,
PacketNumber: protocol.PacketNumber(pn),
PacketNumberLen: pnLen,
}, nil
@ -120,7 +125,7 @@ func (h *Header) writeHeader(b *bytes.Buffer) error {
// TODO: add support for the key phase
func (h *Header) writeLongHeader(b *bytes.Buffer) error {
b.WriteByte(byte(0x80 | h.Type))
utils.BigEndian.WriteUint64(b, uint64(h.ConnectionID))
b.Write(h.ConnectionID)
utils.BigEndian.WriteUint32(b, uint32(h.Version))
utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
return nil
@ -144,7 +149,7 @@ func (h *Header) writeShortHeader(b *bytes.Buffer) error {
b.WriteByte(typeByte)
if !h.OmitConnectionID {
utils.BigEndian.WriteUint64(b, uint64(h.ConnectionID))
b.Write(h.ConnectionID)
}
switch h.PacketNumberLen {
case protocol.PacketNumberLen1:

View file

@ -19,30 +19,33 @@ var _ = Describe("IETF draft 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(0x1234567890, versions)
data := ComposeVersionNegotiation(connID, versions)
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(protocol.ConnectionID(0x1234567890)))
Expect(h.ConnectionID).To(Equal(connID))
for _, v := range versions {
Expect(h.SupportedVersions).To(ContainElement(v))
}
})
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(0x1234567890, versions)
data := ComposeVersionNegotiation(connID, versions)
b := bytes.NewReader(data[:len(data)-2])
_, 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(0x1234567890, versions)
data := ComposeVersionNegotiation(connID, versions)
// remove 8 bytes (two versions), since ComposeVersionNegotiation also added a reserved version number
_, err := parseHeader(bytes.NewReader(data[:len(data)-8]), protocol.PerspectiveServer)
Expect(err).To(MatchError("InvalidVersionNegotiationPacket: empty version list"))
@ -66,7 +69,7 @@ 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(0xdeadbeefcafe1337)))
Expect(h.ConnectionID).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)))
@ -125,7 +128,7 @@ 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(0xdeadbeefcafe1337)))
Expect(h.ConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}))
Expect(h.PacketNumber).To(Equal(protocol.PacketNumber(0x42)))
Expect(h.IsVersionNegotiation).To(BeFalse())
Expect(b.Len()).To(BeZero())
@ -213,7 +216,7 @@ var _ = Describe("IETF draft Header", func() {
err := (&Header{
IsLongHeader: true,
Type: 0x5,
ConnectionID: 0xdeadbeefcafe1337,
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
PacketNumber: 0xdecafbad,
Version: 0x1020304,
}).writeHeader(buf)
@ -230,7 +233,7 @@ var _ = Describe("IETF draft Header", func() {
Context("short header", func() {
It("writes a header with connection ID", func() {
err := (&Header{
ConnectionID: 0xdeadbeefcafe1337,
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 0x42,
}).writeHeader(buf)
@ -314,7 +317,10 @@ var _ = Describe("IETF draft Header", func() {
})
It("has the right length for the long header", func() {
h := &Header{IsLongHeader: true}
h := &Header{
IsLongHeader: true,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
}
Expect(h.getHeaderLength()).To(Equal(protocol.ByteCount(17)))
err := h.writeHeader(buf)
Expect(err).ToNot(HaveOccurred())
@ -324,6 +330,7 @@ var _ = Describe("IETF draft Header", func() {
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},
}
Expect(h.getHeaderLength()).To(Equal(protocol.ByteCount(1 + 8 + 1)))
err := h.writeHeader(buf)
@ -393,10 +400,10 @@ var _ = Describe("IETF draft Header", func() {
IsLongHeader: true,
Type: protocol.PacketTypeHandshake,
PacketNumber: 0x1337,
ConnectionID: 0xdeadbeef,
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
Version: 0xfeed,
}).logHeader(logger)
Expect(buf.String()).To(ContainSubstring("Long Header{Type: Handshake, ConnectionID: 0xdeadbeef, PacketNumber: 0x1337, Version: 0xfeed}"))
Expect(buf.String()).To(ContainSubstring("Long Header{Type: Handshake, ConnectionID: 0xdeadbeefcafe1337, PacketNumber: 0x1337, Version: 0xfeed}"))
})
It("logs Short Headers containing a connection ID", func() {
@ -404,9 +411,9 @@ var _ = Describe("IETF draft Header", func() {
KeyPhase: 1,
PacketNumber: 0x1337,
PacketNumberLen: 4,
ConnectionID: 0xdeadbeef,
ConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37},
}).logHeader(logger)
Expect(buf.String()).To(ContainSubstring("Short Header{ConnectionID: 0xdeadbeef, PacketNumber: 0x1337, PacketNumberLen: 4, KeyPhase: 1}"))
Expect(buf.String()).To(ContainSubstring("Short Header{ConnectionID: 0xdeadbeefcafe1337, PacketNumber: 0x1337, PacketNumberLen: 4, KeyPhase: 1}"))
})
It("logs Short Headers with omitted connection ID", func() {
@ -414,6 +421,7 @@ var _ = Describe("IETF draft Header", func() {
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}"))
})

View file

@ -26,6 +26,9 @@ 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))
}
publicFlagByte := uint8(0x00)
if h.VersionFlag {
@ -59,7 +62,7 @@ func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _
b.WriteByte(publicFlagByte)
if !h.OmitConnectionID {
utils.BigEndian.WriteUint64(b, uint64(h.ConnectionID))
b.Write(h.ConnectionID)
}
if h.VersionFlag && pers == protocol.PerspectiveClient {
utils.BigEndian.WriteUint32(b, uint32(h.Version))
@ -126,15 +129,18 @@ func parsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Hea
// Connection ID
if !header.OmitConnectionID {
var connID uint64
connID, err = utils.BigEndian.ReadUint64(b)
if err != nil {
connID := make(protocol.ConnectionID, 8)
if _, err := io.ReadFull(b, connID); err != nil {
if err == io.ErrUnexpectedEOF {
err = io.EOF
}
return nil, err
}
header.ConnectionID = protocol.ConnectionID(connID)
if header.ConnectionID == 0 {
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
}
// 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.

View file

@ -24,7 +24,7 @@ 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(0x4cfa9f9b668619f6)))
Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}))
Expect(hdr.Version).To(Equal(protocol.SupportedVersions[0]))
Expect(hdr.SupportedVersions).To(BeEmpty())
Expect(hdr.PacketNumber).To(Equal(protocol.PacketNumber(1)))
@ -42,7 +42,7 @@ var _ = Describe("Public Header", func() {
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.OmitConnectionID).To(BeTrue())
Expect(hdr.ConnectionID).To(BeZero())
Expect(hdr.ConnectionID).To(BeEmpty())
Expect(b.Len()).To(BeZero())
})
@ -52,22 +52,22 @@ var _ = Describe("Public Header", func() {
Expect(err).To(MatchError(errInvalidConnectionID))
})
It("reads a PublicReset packet", func() {
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(BeZero())
Expect(hdr.ConnectionID).ToNot(BeEmpty())
})
It("parses a public reset packet", func() {
b := bytes.NewReader([]byte{0xa, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08})
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)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.ResetFlag).To(BeTrue())
Expect(hdr.VersionFlag).To(BeFalse())
Expect(hdr.IsVersionNegotiation).To(BeFalse())
Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID(0x0102030405060708)))
Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}))
})
It("reads a diversification nonce sent by the server", func() {
@ -76,7 +76,7 @@ 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(BeZero()))
Expect(hdr.ConnectionID).To(Not(BeEmpty()))
Expect(hdr.DiversificationNonce).To(Equal(divNonce))
Expect(b.Len()).To(BeZero())
})
@ -89,10 +89,12 @@ var _ = Describe("Public Header", func() {
}
It("parses", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
versions := []protocol.VersionNumber{0x13, 0x37}
b := bytes.NewReader(ComposeGQUICVersionNegotiation(0x1337, versions))
b := bytes.NewReader(ComposeGQUICVersionNegotiation(connID, versions))
hdr, err := parsePublicHeader(b, protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.Version).To(BeZero()) // unitialized
Expect(hdr.IsVersionNegotiation).To(BeTrue())
@ -124,7 +126,7 @@ var _ = Describe("Public Header", func() {
})
It("errors on invalid version tags", func() {
data := ComposeGQUICVersionNegotiation(0x1337, protocol.SupportedVersions)
data := ComposeGQUICVersionNegotiation(protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}, protocol.SupportedVersions)
data = append(data, []byte{0x13, 0x37}...)
b := bytes.NewReader(data)
_, err := parsePublicHeader(b, protocol.PerspectiveServer)
@ -175,7 +177,7 @@ var _ = Describe("Public Header", func() {
It("writes a sample header as a server", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen6,
}
@ -187,7 +189,7 @@ var _ = Describe("Public Header", func() {
It("writes a sample header as a client", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen6,
}
@ -196,9 +198,20 @@ var _ = Describe("Public Header", func() {
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() {
hdr := Header{
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7},
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen2,
}
b := &bytes.Buffer{}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(err).To(MatchError("PublicHeader: wrong length for Connection ID: 7 (expected 8)"))
})
It("refuses to write a Public Header if the PacketNumberLen is not set", func() {
hdr := Header{
ConnectionID: 1,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
PacketNumber: 2,
}
b := &bytes.Buffer{}
@ -209,7 +222,7 @@ var _ = Describe("Public Header", func() {
It("omits the connection ID", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
OmitConnectionID: true,
PacketNumberLen: protocol.PacketNumberLen1,
PacketNumber: 1,
@ -222,7 +235,7 @@ var _ = Describe("Public Header", func() {
It("writes diversification nonces", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen1,
DiversificationNonce: bytes.Repeat([]byte{1}, 32),
@ -250,7 +263,7 @@ var _ = Describe("Public Header", func() {
b := &bytes.Buffer{}
hdr := Header{
VersionFlag: true,
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen6,
}
@ -263,7 +276,7 @@ var _ = Describe("Public Header", func() {
hdr := Header{
VersionFlag: true,
Version: protocol.Version39,
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0x42,
PacketNumberLen: protocol.PacketNumberLen1,
}
@ -283,7 +296,7 @@ var _ = Describe("Public Header", func() {
b := &bytes.Buffer{}
hdr := Header{
ResetFlag: true,
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(err).ToNot(HaveOccurred())
@ -297,7 +310,7 @@ var _ = Describe("Public Header", func() {
b := &bytes.Buffer{}
hdr := Header{
ResetFlag: true,
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 2,
PacketNumberLen: protocol.PacketNumberLen6,
}
@ -326,7 +339,7 @@ var _ = Describe("Public Header", func() {
It("errors when PacketNumberLen is not set", func() {
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xdecafbad,
}
_, err := hdr.getPublicHeaderLength(protocol.PerspectiveServer)
@ -335,7 +348,7 @@ var _ = Describe("Public Header", func() {
It("gets the length of a packet with longest packet number length and connectionID", func() {
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen6,
}
@ -346,7 +359,7 @@ var _ = Describe("Public Header", func() {
It("gets the lengths of a packet sent by the client with the VersionFlag set", func() {
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
OmitConnectionID: true,
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen6,
@ -360,7 +373,7 @@ var _ = Describe("Public Header", func() {
It("gets the length of a packet with longest packet number length and omitted connectionID", func() {
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
OmitConnectionID: true,
PacketNumber: 0xDECAFBAD,
PacketNumberLen: protocol.PacketNumberLen6,
@ -372,7 +385,7 @@ var _ = Describe("Public Header", func() {
It("gets the length of a packet 2 byte packet number length ", func() {
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xDECAFBAD,
PacketNumberLen: protocol.PacketNumberLen2,
}
@ -394,7 +407,7 @@ var _ = Describe("Public Header", func() {
It("gets the length of a PublicReset", func() {
hdr := Header{
ResetFlag: true,
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
}
length, err := hdr.getPublicHeaderLength(protocol.PerspectiveServer)
Expect(err).NotTo(HaveOccurred())
@ -406,7 +419,7 @@ 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: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xDECAFBAD,
}
err := hdr.writePublicHeader(b, protocol.PerspectiveServer, protocol.VersionWhatever)
@ -419,7 +432,7 @@ var _ = Describe("Public Header", func() {
It("writes a header with a 1-byte packet number", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen1,
}
@ -431,7 +444,7 @@ var _ = Describe("Public Header", func() {
It("writes a header with a 2-byte packet number", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xdecafbad,
PacketNumberLen: protocol.PacketNumberLen2,
}
@ -443,7 +456,7 @@ var _ = Describe("Public Header", func() {
It("writes a header with a 4-byte packet number", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0x13decafbad,
PacketNumberLen: protocol.PacketNumberLen4,
}
@ -455,7 +468,7 @@ var _ = Describe("Public Header", func() {
It("writes a header with a 6-byte packet number", func() {
b := &bytes.Buffer{}
hdr := Header{
ConnectionID: 0x4cfa9f9b668619f6,
ConnectionID: protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6},
PacketNumber: 0xbe1337decafbad,
PacketNumberLen: protocol.PacketNumberLen6,
}
@ -486,12 +499,12 @@ var _ = Describe("Public Header", func() {
It("logs a Public Header containing a connection ID", func() {
(&Header{
ConnectionID: 0xdecafbad,
ConnectionID: 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: 0xdecafbad, PacketNumber: 0x1337, PacketNumberLen: 6, Version: gQUIC 39"))
Expect(buf.String()).To(ContainSubstring("Public Header{ConnectionID: 0x13370000decafbad, PacketNumber: 0x1337, PacketNumberLen: 6, Version: gQUIC 39"))
})
It("logs a Public Header with omitted connection ID", func() {
@ -515,7 +528,7 @@ var _ = Describe("Public Header", func() {
It("logs diversification nonces", func() {
(&Header{
ConnectionID: 0xdecafbad,
ConnectionID: []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

@ -16,11 +16,11 @@ type PublicReset struct {
Nonce uint64
}
// WritePublicReset writes a Public Reset
// WritePublicReset writes a PUBLIC_RESET
func WritePublicReset(connectionID protocol.ConnectionID, rejectedPacketNumber protocol.PacketNumber, nonceProof uint64) []byte {
b := &bytes.Buffer{}
b.WriteByte(0x0a)
utils.BigEndian.WriteUint64(b, uint64(connectionID))
b.Write(connectionID)
utils.LittleEndian.WriteUint32(b, uint32(handshake.TagPRST))
utils.LittleEndian.WriteUint32(b, 2)
utils.LittleEndian.WriteUint32(b, uint32(handshake.TagRNON))
@ -32,7 +32,7 @@ func WritePublicReset(connectionID protocol.ConnectionID, rejectedPacketNumber p
return b.Bytes()
}
// ParsePublicReset parses a Public Reset
// ParsePublicReset parses a PUBLIC_RESET
func ParsePublicReset(r *bytes.Reader) (*PublicReset, error) {
pr := PublicReset{}
msg, err := handshake.ParseHandshakeMessage(r)
@ -44,7 +44,7 @@ func ParsePublicReset(r *bytes.Reader) (*PublicReset, error) {
}
// The RSEQ tag is mandatory according to the gQUIC wire spec.
// However, Google doesn't send RSEQ in their Public Resets.
// However, Google doesn't send RSEQ in their PUBLIC_RESETs.
// Therefore, we'll treat RSEQ as an optional field.
if rseq, ok := msg.Data[handshake.TagRSEQ]; ok {
if len(rseq) != 8 {

View file

@ -13,7 +13,7 @@ import (
var _ = Describe("public reset", func() {
Context("writing", func() {
It("writes public reset packets", func() {
Expect(WritePublicReset(0xdeadbeef, 0x8badf00d, 0xdecafbad)).To(Equal([]byte{
Expect(WritePublicReset(protocol.ConnectionID{0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef}, 0x8badf00d, 0xdecafbad)).To(Equal([]byte{
0x0a,
0x0, 0x0, 0x0, 0x0, 0xde, 0xad, 0xbe, 0xef,
'P', 'R', 'S', 'T',
@ -36,7 +36,7 @@ var _ = Describe("public reset", func() {
})
It("parses a public reset", func() {
packet := WritePublicReset(0xdeadbeef, 0x8badf00d, 0xdecafbad)
packet := WritePublicReset(protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}, 0x8badf00d, 0xdecafbad)
pr, err := ParsePublicReset(bytes.NewReader(packet[9:])) // 1 byte Public Flag, 8 bytes connection ID
Expect(err).ToNot(HaveOccurred())
Expect(pr.Nonce).To(Equal(uint64(0xdecafbad)))

View file

@ -12,7 +12,7 @@ import (
func ComposeGQUICVersionNegotiation(connID protocol.ConnectionID, versions []protocol.VersionNumber) []byte {
buf := bytes.NewBuffer(make([]byte, 0, 1+8+len(versions)*4))
buf.Write([]byte{0x1 | 0x8}) // type byte
utils.BigEndian.WriteUint64(buf, uint64(connID))
buf.Write(connID)
for _, v := range versions {
utils.BigEndian.WriteUint32(buf, uint32(v))
}
@ -20,16 +20,13 @@ 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(connID protocol.ConnectionID, versions []protocol.VersionNumber) []byte {
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)
utils.BigEndian.WriteUint64(buf, uint64(connID))
buf.Write(connID)
utils.BigEndian.WriteUint32(buf, 0) // version 0
for _, v := range greasedVersions {
utils.BigEndian.WriteUint32(buf, uint32(v))

View file

@ -10,23 +10,25 @@ import (
var _ = Describe("Version Negotiation Packets", func() {
It("writes for gQUIC", func() {
connID := protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}
versions := []protocol.VersionNumber{1001, 1003}
data := ComposeGQUICVersionNegotiation(0x1337, versions)
data := ComposeGQUICVersionNegotiation(connID, versions)
hdr, err := parsePublicHeader(bytes.NewReader(data), protocol.PerspectiveServer)
Expect(err).ToNot(HaveOccurred())
Expect(hdr.VersionFlag).To(BeTrue())
Expect(hdr.ConnectionID).To(Equal(protocol.ConnectionID(0x1337)))
Expect(hdr.ConnectionID).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}
versions := []protocol.VersionNumber{1001, 1003}
data := ComposeVersionNegotiation(0x1337, versions)
data := ComposeVersionNegotiation(connID, versions)
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(protocol.ConnectionID(0x1337)))
Expect(hdr.ConnectionID).To(Equal(connID))
Expect(hdr.Version).To(BeZero())
// the supported versions should include one reserved version number
Expect(hdr.SupportedVersions).To(HaveLen(len(versions) + 1))

View file

@ -17,7 +17,7 @@ import (
var _ = Describe("Packing and unpacking Initial packets", func() {
var aead crypto.AEAD
connID := protocol.ConnectionID(0x1337)
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
ver := protocol.VersionTLS
hdr := &wire.Header{
IsLongHeader: true,

View file

@ -67,7 +67,7 @@ var _ = Describe("Packet packer", func() {
divNonce = bytes.Repeat([]byte{'e'}, 32)
packer = newPacketPacker(
0x1337,
protocol.ConnectionID{0, 0, 0, 0, 0, 0, 0x13, 0x37},
1,
func(protocol.PacketNumber) protocol.PacketNumberLen { return protocol.PacketNumberLen2 },
&net.TCPAddr{},
@ -85,22 +85,23 @@ var _ = Describe("Packet packer", func() {
})
Context("determining the maximum packet size", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
It("uses the minimum initial size, if it can't determine if the remote address is IPv4 or IPv6", func() {
remoteAddr := &net.TCPAddr{}
packer = newPacketPacker(0x1337, 1, nil, remoteAddr, nil, nil, nil, protocol.PerspectiveServer, protocol.VersionWhatever)
packer = newPacketPacker(connID, 1, nil, remoteAddr, nil, nil, nil, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(packer.maxPacketSize).To(BeEquivalentTo(protocol.MinInitialPacketSize))
})
It("uses the maximum IPv4 packet size, if the remote address is IPv4", func() {
remoteAddr := &net.UDPAddr{IP: net.IPv4(11, 12, 13, 14), Port: 1337}
packer = newPacketPacker(0x1337, 1, nil, remoteAddr, nil, nil, nil, protocol.PerspectiveServer, protocol.VersionWhatever)
packer = newPacketPacker(connID, 1, nil, remoteAddr, nil, nil, nil, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(packer.maxPacketSize).To(BeEquivalentTo(protocol.MaxPacketSizeIPv4))
})
It("uses the maximum IPv6 packet size, if the remote address is IPv6", func() {
ip := net.ParseIP("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
remoteAddr := &net.UDPAddr{IP: ip, Port: 1337}
packer = newPacketPacker(0x1337, 1, nil, remoteAddr, nil, nil, nil, protocol.PerspectiveServer, protocol.VersionWhatever)
packer = newPacketPacker(connID, 1, nil, remoteAddr, nil, nil, nil, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(packer.maxPacketSize).To(BeEquivalentTo(protocol.MaxPacketSizeIPv6))
})
})

View file

@ -42,7 +42,7 @@ type server struct {
scfg *handshake.ServerConfig
sessionsMutex sync.RWMutex
sessions map[protocol.ConnectionID]packetHandler
sessions map[string] /* string(ConnectionID)*/ packetHandler
closed bool
serverError error
@ -106,7 +106,7 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener,
config: config,
certChain: certChain,
scfg: scfg,
sessions: map[protocol.ConnectionID]packetHandler{},
sessions: map[string]packetHandler{},
newSession: newSession,
deleteClosedSessionsAfter: protocol.ClosedSessionDeleteTimeout,
sessionQueue: make(chan Session, 5),
@ -144,11 +144,11 @@ func (s *server) setupTLS() error {
connID := tlsSession.connID
sess := tlsSession.sess
s.sessionsMutex.Lock()
if _, ok := s.sessions[connID]; ok { // drop this session if it already exists
if _, ok := s.sessions[string(connID)]; ok { // drop this session if it already exists
s.sessionsMutex.Unlock()
continue
}
s.sessions[connID] = sess
s.sessions[string(connID)] = sess
s.sessionsMutex.Unlock()
s.runHandshakeAndSession(sess, connID)
}
@ -317,7 +317,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
}
s.sessionsMutex.RLock()
session, sessionKnown := s.sessions[connID]
session, sessionKnown := s.sessions[string(connID)]
s.sessionsMutex.RUnlock()
if sessionKnown && session == nil {
@ -394,7 +394,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
return err
}
s.sessionsMutex.Lock()
s.sessions[connID] = session
s.sessions[string(connID)] = session
s.sessionsMutex.Unlock()
s.runHandshakeAndSession(session, connID)
@ -425,12 +425,12 @@ func (s *server) runHandshakeAndSession(session packetHandler, connID protocol.C
func (s *server) removeConnection(id protocol.ConnectionID) {
s.sessionsMutex.Lock()
s.sessions[id] = nil
s.sessions[string(id)] = nil
s.sessionsMutex.Unlock()
time.AfterFunc(s.deleteClosedSessionsAfter, func() {
s.sessionsMutex.Lock()
delete(s.sessions, id)
delete(s.sessions, string(id))
s.sessionsMutex.Unlock()
})
}

View file

@ -106,12 +106,12 @@ var _ = Describe("Server", func() {
var (
serv *server
firstPacket []byte // a valid first packet for a new connection with connectionID 0x4cfa9f9b668619f6 (= connID)
connID = protocol.ConnectionID(0x4cfa9f9b668619f6)
connID = protocol.ConnectionID{0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}
)
BeforeEach(func() {
serv = &server{
sessions: make(map[protocol.ConnectionID]packetHandler),
sessions: make(map[string]packetHandler),
newSession: newMockSession,
conn: conn,
config: config,
@ -174,13 +174,13 @@ var _ = Describe("Server", func() {
err := serv.handlePacket(nil, nil, firstPacket)
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
sess := serv.sessions[connID].(*mockSession)
sess := serv.sessions[string(connID)].(*mockSession)
Expect(sess.connectionID).To(Equal(connID))
Expect(sess.packetCount).To(Equal(1))
})
It("accepts new TLS sessions", func() {
connID := protocol.ConnectionID(0x12345)
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
sess, err := newMockSession(nil, protocol.VersionTLS, connID, nil, nil, nil, nil)
Expect(err).ToNot(HaveOccurred())
err = serv.setupTLS()
@ -192,12 +192,12 @@ var _ = Describe("Server", func() {
Eventually(func() packetHandler {
serv.sessionsMutex.Lock()
defer serv.sessionsMutex.Unlock()
return serv.sessions[connID]
return serv.sessions[string(connID)]
}).Should(Equal(sess))
})
It("only accepts one new TLS sessions for one connection ID", func() {
connID := protocol.ConnectionID(0x12345)
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
sess1, err := newMockSession(nil, protocol.VersionTLS, connID, nil, nil, nil, nil)
Expect(err).ToNot(HaveOccurred())
sess2, err := newMockSession(nil, protocol.VersionTLS, connID, nil, nil, nil, nil)
@ -211,7 +211,7 @@ var _ = Describe("Server", func() {
Eventually(func() packetHandler {
serv.sessionsMutex.Lock()
defer serv.sessionsMutex.Unlock()
return serv.sessions[connID]
return serv.sessions[string(connID)]
}).Should(Equal(sess1))
serv.serverTLS.sessionChan <- tlsSession{
connID: connID,
@ -220,7 +220,7 @@ var _ = Describe("Server", func() {
Eventually(func() packetHandler {
serv.sessionsMutex.Lock()
defer serv.sessionsMutex.Unlock()
return serv.sessions[connID]
return serv.sessions[string(connID)]
}).Should(Equal(sess1))
})
@ -235,7 +235,7 @@ var _ = Describe("Server", func() {
err := serv.handlePacket(nil, nil, firstPacket)
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
sess := serv.sessions[connID].(*mockSession)
sess := serv.sessions[string(connID)].(*mockSession)
Consistently(func() Session { return acceptedSess }).Should(BeNil())
close(sess.handshakeChan)
Eventually(func() Session { return acceptedSess }).Should(Equal(sess))
@ -252,7 +252,7 @@ var _ = Describe("Server", func() {
err := serv.handlePacket(nil, nil, firstPacket)
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
sess := serv.sessions[connID].(*mockSession)
sess := serv.sessions[string(connID)].(*mockSession)
sess.handshakeChan <- errors.New("handshake failed")
Consistently(func() bool { return accepted }).Should(BeFalse())
close(done)
@ -264,8 +264,8 @@ var _ = Describe("Server", func() {
err = serv.handlePacket(nil, nil, []byte{0x08, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0x01})
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
Expect(serv.sessions[connID].(*mockSession).connectionID).To(Equal(connID))
Expect(serv.sessions[connID].(*mockSession).packetCount).To(Equal(2))
Expect(serv.sessions[string(connID)].(*mockSession).connectionID).To(Equal(connID))
Expect(serv.sessions[string(connID)].(*mockSession).packetCount).To(Equal(2))
})
It("closes and deletes sessions", func() {
@ -275,12 +275,12 @@ var _ = Describe("Server", func() {
err = serv.handlePacket(nil, nil, append(firstPacket, nullAEAD.Seal(nil, nil, 0, firstPacket)...))
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
Expect(serv.sessions[connID]).ToNot(BeNil())
Expect(serv.sessions[string(connID)]).ToNot(BeNil())
// make session.run() return
serv.sessions[connID].(*mockSession).stopRunLoop <- struct{}{}
serv.sessions[string(connID)].(*mockSession).stopRunLoop <- struct{}{}
// The server should now have closed the session, leaving a nil value in the sessions map
Consistently(func() map[protocol.ConnectionID]packetHandler { return serv.sessions }).Should(HaveLen(1))
Expect(serv.sessions[connID]).To(BeNil())
Consistently(func() map[string]packetHandler { return serv.sessions }).Should(HaveLen(1))
Expect(serv.sessions[string(connID)]).To(BeNil())
})
It("deletes nil session entries after a wait time", func() {
@ -290,12 +290,12 @@ var _ = Describe("Server", func() {
err = serv.handlePacket(nil, nil, append(firstPacket, nullAEAD.Seal(nil, nil, 0, firstPacket)...))
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
Expect(serv.sessions).To(HaveKey(connID))
Expect(serv.sessions).To(HaveKey(string(connID)))
// make session.run() return
serv.sessions[connID].(*mockSession).stopRunLoop <- struct{}{}
serv.sessions[string(connID)].(*mockSession).stopRunLoop <- struct{}{}
Eventually(func() bool {
serv.sessionsMutex.Lock()
_, ok := serv.sessions[connID]
_, ok := serv.sessions[string(connID)]
serv.sessionsMutex.Unlock()
return ok
}).Should(BeFalse())
@ -303,8 +303,8 @@ var _ = Describe("Server", func() {
It("closes sessions and the connection when Close is called", func() {
go serv.serve()
session, _ := newMockSession(nil, 0, 0, nil, nil, nil, nil)
serv.sessions[1] = session
session, _ := newMockSession(nil, 0, connID, nil, nil, nil, nil)
serv.sessions[string(connID)] = session
err := serv.Close()
Expect(err).NotTo(HaveOccurred())
Expect(session.(*mockSession).closed).To(BeTrue())
@ -312,11 +312,11 @@ var _ = Describe("Server", func() {
})
It("ignores packets for closed sessions", func() {
serv.sessions[connID] = nil
serv.sessions[string(connID)] = nil
err := serv.handlePacket(nil, nil, []byte{0x08, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6, 0x01})
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
Expect(serv.sessions[connID]).To(BeNil())
Expect(serv.sessions[string(connID)]).To(BeNil())
})
It("works if no quic.Config is given", func(done Done) {
@ -353,9 +353,9 @@ var _ = Describe("Server", func() {
}, 0.5)
It("closes all sessions when encountering a connection error", func() {
session, _ := newMockSession(nil, 0, 0, nil, nil, nil, nil)
serv.sessions[0x12345] = session
Expect(serv.sessions[0x12345].(*mockSession).closed).To(BeFalse())
session, _ := newMockSession(nil, 0, connID, nil, nil, nil, nil)
serv.sessions[string(connID)] = session
Expect(serv.sessions[string(connID)].(*mockSession).closed).To(BeFalse())
testErr := errors.New("connection error")
conn.readErr = testErr
go serv.serve()
@ -366,7 +366,7 @@ var _ = Describe("Server", func() {
It("ignores delayed packets with mismatching versions", func() {
err := serv.handlePacket(nil, nil, firstPacket)
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions[connID].(*mockSession).packetCount).To(Equal(1))
Expect(serv.sessions[string(connID)].(*mockSession).packetCount).To(Equal(1))
b := &bytes.Buffer{}
// add an unsupported version
data := []byte{0x09, 0x4c, 0xfa, 0x9f, 0x9b, 0x66, 0x86, 0x19, 0xf6}
@ -377,7 +377,7 @@ var _ = Describe("Server", func() {
// if we didn't ignore the packet, the server would try to send a version negotiation packet, which would make the test panic because it doesn't have a udpConn
Expect(conn.dataWritten.Bytes()).To(BeEmpty())
// make sure the packet was *not* passed to session.handlePacket()
Expect(serv.sessions[connID].(*mockSession).packetCount).To(Equal(1))
Expect(serv.sessions[string(connID)].(*mockSession).packetCount).To(Equal(1))
})
It("errors on invalid public header", func() {
@ -386,7 +386,7 @@ var _ = Describe("Server", func() {
})
It("ignores public resets for unknown connections", func() {
err := serv.handlePacket(nil, nil, wire.WritePublicReset(999, 1, 1337))
err := serv.handlePacket(nil, nil, wire.WritePublicReset([]byte{9, 9, 9, 9, 9, 9, 9, 9}, 1, 1337))
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(BeEmpty())
})
@ -395,23 +395,23 @@ var _ = Describe("Server", func() {
err := serv.handlePacket(nil, nil, firstPacket)
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
Expect(serv.sessions[connID].(*mockSession).packetCount).To(Equal(1))
Expect(serv.sessions[string(connID)].(*mockSession).packetCount).To(Equal(1))
err = serv.handlePacket(nil, nil, wire.WritePublicReset(connID, 1, 1337))
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
Expect(serv.sessions[connID].(*mockSession).packetCount).To(Equal(1))
Expect(serv.sessions[string(connID)].(*mockSession).packetCount).To(Equal(1))
})
It("ignores invalid public resets for known connections", func() {
err := serv.handlePacket(nil, nil, firstPacket)
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
Expect(serv.sessions[connID].(*mockSession).packetCount).To(Equal(1))
Expect(serv.sessions[string(connID)].(*mockSession).packetCount).To(Equal(1))
data := wire.WritePublicReset(connID, 1, 1337)
err = serv.handlePacket(nil, nil, data[:len(data)-2])
Expect(err).ToNot(HaveOccurred())
Expect(serv.sessions).To(HaveLen(1))
Expect(serv.sessions[connID].(*mockSession).packetCount).To(Equal(1))
Expect(serv.sessions[string(connID)].(*mockSession).packetCount).To(Equal(1))
})
It("doesn't try to process a packet after sending a gQUIC Version Negotiation Packet", func() {
@ -419,7 +419,7 @@ var _ = Describe("Server", func() {
b := &bytes.Buffer{}
hdr := wire.Header{
VersionFlag: true,
ConnectionID: 0x1337,
ConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
}
@ -434,7 +434,7 @@ var _ = Describe("Server", func() {
b := &bytes.Buffer{}
hdr := wire.Header{
VersionFlag: true,
ConnectionID: 0x1337,
ConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
}
@ -507,10 +507,11 @@ var _ = Describe("Server", func() {
})
It("sends a gQUIC Version Negotaion Packet, if the client sent a gQUIC Public Header", func() {
connID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
b := &bytes.Buffer{}
hdr := wire.Header{
VersionFlag: true,
ConnectionID: 0x1337,
ConnectionID: connID,
PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2,
}
@ -534,7 +535,7 @@ 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(protocol.ConnectionID(0x1337)))
Expect(packet.ConnectionID).To(Equal(connID))
Expect(r.Len()).To(BeZero())
Consistently(done).ShouldNot(BeClosed())
// make the go routine return
@ -543,12 +544,13 @@ var _ = Describe("Server", func() {
})
It("sends an IETF draft style Version Negotaion Packet, if the client sent a IETF draft style header", func() {
connID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
config.Versions = append(config.Versions, protocol.VersionTLS)
b := &bytes.Buffer{}
hdr := wire.Header{
Type: protocol.PacketTypeInitial,
IsLongHeader: true,
ConnectionID: 0x1337,
ConnectionID: connID,
PacketNumber: 0x55,
Version: 0x1234,
}
@ -573,7 +575,7 @@ 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(protocol.ConnectionID(0x1337)))
Expect(packet.ConnectionID).To(Equal(connID))
Expect(r.Len()).To(BeZero())
Consistently(done).ShouldNot(BeClosed())
// make the go routine return
@ -582,11 +584,12 @@ var _ = Describe("Server", func() {
})
It("ignores IETF draft style Initial packets, if it doesn't support TLS", func() {
connID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
b := &bytes.Buffer{}
hdr := wire.Header{
Type: protocol.PacketTypeInitial,
IsLongHeader: true,
ConnectionID: 0x1337,
ConnectionID: connID,
PacketNumber: 0x55,
Version: protocol.VersionTLS,
}

View file

@ -46,16 +46,18 @@ var _ = Describe("Stateless TLS handling", func() {
})
getPacket := func(f wire.Frame) (*wire.Header, []byte) {
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,
}
err := hdr.Write(hdrBuf, protocol.PerspectiveClient, protocol.VersionTLS)
Expect(err).ToNot(HaveOccurred())
hdr.Raw = hdrBuf.Bytes()
aead, err := crypto.NewNullAEAD(protocol.PerspectiveClient, 0, protocol.VersionTLS)
aead, err := crypto.NewNullAEAD(protocol.PerspectiveClient, connID, protocol.VersionTLS)
Expect(err).ToNot(HaveOccurred())
buf := &bytes.Buffer{}
err = f.Write(buf, protocol.VersionTLS)
@ -80,7 +82,11 @@ var _ = Describe("Stateless TLS handling", func() {
}
It("sends a version negotiation packet if it doesn't support the version", func() {
server.HandleInitial(nil, &wire.Header{Version: 0x1337}, bytes.Repeat([]byte{0}, protocol.MinInitialPacketSize))
hdr := &wire.Header{
ConnectionID: 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())
hdr, err := wire.ParseHeaderSentByServer(bytes.NewReader(conn.dataWritten.Bytes()), protocol.VersionUnknown)
Expect(err).ToNot(HaveOccurred())

View file

@ -107,7 +107,7 @@ var _ = Describe("Session", func() {
pSess, err = newSession(
mconn,
protocol.Version39,
0,
protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1},
scfg,
nil,
populateServerConfig(&Config{}),
@ -160,7 +160,7 @@ var _ = Describe("Session", func() {
pSess, err := newSession(
mconn,
protocol.Version39,
0,
protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1},
scfg,
nil,
conf,
@ -1748,7 +1748,7 @@ var _ = Describe("Client Session", func() {
mconn,
"hostname",
protocol.Version39,
0,
protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1},
nil,
populateClientConfig(&Config{}),
protocol.VersionWhatever,