forked from quic-go/quic-go
move processing of transport parameters to the session
This commit is contained in:
231
session_test.go
231
session_test.go
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
@@ -91,7 +92,7 @@ var _ = Describe("Session", func() {
|
||||
protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
|
||||
populateServerConfig(&Config{}),
|
||||
nil, // tls.Config
|
||||
nil, // handshake.TransportParameters,
|
||||
&handshake.TransportParameters{},
|
||||
utils.DefaultLogger,
|
||||
protocol.VersionTLS,
|
||||
)
|
||||
@@ -1085,28 +1086,71 @@ var _ = Describe("Session", func() {
|
||||
Eventually(done).Should(BeClosed())
|
||||
})
|
||||
|
||||
It("process transport parameters received from the peer", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
cryptoSetup.EXPECT().RunHandshake().Do(func() { <-sess.Context().Done() })
|
||||
sess.run()
|
||||
}()
|
||||
params := &handshake.TransportParameters{
|
||||
IdleTimeout: 90 * time.Second,
|
||||
InitialMaxStreamDataBidiLocal: 0x5000,
|
||||
InitialMaxData: 0x5000,
|
||||
MaxPacketSize: 0x42,
|
||||
}
|
||||
streamManager.EXPECT().UpdateLimits(params)
|
||||
packer.EXPECT().HandleTransportParameters(params)
|
||||
sess.processTransportParameters(params)
|
||||
// make the go routine return
|
||||
streamManager.EXPECT().CloseWithError(gomock.Any())
|
||||
sessionRunner.EXPECT().retireConnectionID(gomock.Any())
|
||||
packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&packedPacket{}, nil)
|
||||
cryptoSetup.EXPECT().Close()
|
||||
sess.Close()
|
||||
Eventually(sess.Context().Done()).Should(BeClosed())
|
||||
Context("transport parameters", func() {
|
||||
It("errors if it can't unmarshal the TransportParameters", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
cryptoSetup.EXPECT().RunHandshake().Do(func() { <-sess.Context().Done() })
|
||||
err := sess.run()
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("transport parameter"))
|
||||
}()
|
||||
streamManager.EXPECT().CloseWithError(gomock.Any())
|
||||
sessionRunner.EXPECT().retireConnectionID(gomock.Any())
|
||||
packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&packedPacket{}, nil)
|
||||
cryptoSetup.EXPECT().Close()
|
||||
sess.processTransportParameters([]byte("invalid"))
|
||||
Eventually(sess.Context().Done()).Should(BeClosed())
|
||||
})
|
||||
|
||||
It("process transport parameters received from the client", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
cryptoSetup.EXPECT().RunHandshake().Do(func() { <-sess.Context().Done() })
|
||||
sess.run()
|
||||
}()
|
||||
params := &handshake.TransportParameters{
|
||||
IdleTimeout: 90 * time.Second,
|
||||
InitialMaxStreamDataBidiLocal: 0x5000,
|
||||
InitialMaxData: 0x5000,
|
||||
// marshaling always sets it to this value
|
||||
MaxPacketSize: protocol.MaxReceivePacketSize,
|
||||
}
|
||||
chtp := &handshake.ClientHelloTransportParameters{
|
||||
InitialVersion: sess.version,
|
||||
Parameters: *params,
|
||||
}
|
||||
streamManager.EXPECT().UpdateLimits(params)
|
||||
packer.EXPECT().HandleTransportParameters(params)
|
||||
sess.processTransportParameters(chtp.Marshal())
|
||||
// make the go routine return
|
||||
streamManager.EXPECT().CloseWithError(gomock.Any())
|
||||
sessionRunner.EXPECT().retireConnectionID(gomock.Any())
|
||||
packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&packedPacket{}, nil)
|
||||
cryptoSetup.EXPECT().Close()
|
||||
sess.Close()
|
||||
Eventually(sess.Context().Done()).Should(BeClosed())
|
||||
})
|
||||
|
||||
It("accepts a valid version negotiation", func() {
|
||||
sess.version = 42
|
||||
sess.config.Versions = []protocol.VersionNumber{13, 37, 42}
|
||||
chtp := &handshake.ClientHelloTransportParameters{
|
||||
InitialVersion: 22, // this must be an unsupported version
|
||||
}
|
||||
_, err := sess.processTransportParametersForServer(chtp.Marshal())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("erros when a version negotiation was performed, although we already support the initial version", func() {
|
||||
sess.version = 42
|
||||
sess.config.Versions = []protocol.VersionNumber{13, 37, 42}
|
||||
chtp := &handshake.ClientHelloTransportParameters{
|
||||
InitialVersion: 13, // this must be a supported version
|
||||
}
|
||||
_, err := sess.processTransportParametersForServer(chtp.Marshal())
|
||||
Expect(err).To(MatchError("VersionNegotiationMismatch: Client should have used the initial version"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("keep-alives", func() {
|
||||
@@ -1394,7 +1438,7 @@ var _ = Describe("Client Session", func() {
|
||||
populateClientConfig(&Config{}, true),
|
||||
nil, // tls.Config
|
||||
42, // initial packet number
|
||||
nil, // transport parameters
|
||||
&handshake.TransportParameters{},
|
||||
protocol.VersionWhatever,
|
||||
utils.DefaultLogger,
|
||||
protocol.VersionWhatever,
|
||||
@@ -1441,4 +1485,143 @@ var _ = Describe("Client Session", func() {
|
||||
Expect(sess.Close()).To(Succeed())
|
||||
Eventually(sess.Context().Done()).Should(BeClosed())
|
||||
})
|
||||
|
||||
Context("transport parameters", func() {
|
||||
It("errors if it can't unmarshal the TransportParameters", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
cryptoSetup.EXPECT().RunHandshake().Do(func() { <-sess.Context().Done() })
|
||||
err := sess.run()
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("transport parameter"))
|
||||
}()
|
||||
// streamManager.EXPECT().CloseWithError(gomock.Any())
|
||||
sessionRunner.EXPECT().retireConnectionID(gomock.Any())
|
||||
packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&packedPacket{}, nil)
|
||||
cryptoSetup.EXPECT().Close()
|
||||
sess.processTransportParameters([]byte("invalid"))
|
||||
Eventually(sess.Context().Done()).Should(BeClosed())
|
||||
})
|
||||
|
||||
It("errors if the TransportParameters don't contain the stateless reset token", func() {
|
||||
eetp := &handshake.EncryptedExtensionsTransportParameters{
|
||||
NegotiatedVersion: sess.version,
|
||||
SupportedVersions: []protocol.VersionNumber{sess.version},
|
||||
}
|
||||
_, err := sess.processTransportParametersForClient(eetp.Marshal())
|
||||
Expect(err).To(MatchError("server didn't send stateless_reset_token"))
|
||||
})
|
||||
|
||||
It("errors if the TransportParameters contain an original_connection_id, although no Retry was performed", func() {
|
||||
eetp := &handshake.EncryptedExtensionsTransportParameters{
|
||||
NegotiatedVersion: sess.version,
|
||||
SupportedVersions: []protocol.VersionNumber{sess.version},
|
||||
Parameters: handshake.TransportParameters{
|
||||
OriginalConnectionID: protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad},
|
||||
StatelessResetToken: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
|
||||
},
|
||||
}
|
||||
_, err := sess.processTransportParametersForClient(eetp.Marshal())
|
||||
Expect(err).To(MatchError(fmt.Sprintf("expected original_connection_id to equal %s, is 0xdecafbad", sess.destConnID)))
|
||||
})
|
||||
|
||||
It("errors if the TransportParameters contain an original_connection_id, although no Retry was performed", func() {
|
||||
sess.origDestConnID = protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}
|
||||
eetp := &handshake.EncryptedExtensionsTransportParameters{
|
||||
NegotiatedVersion: sess.version,
|
||||
SupportedVersions: []protocol.VersionNumber{sess.version},
|
||||
Parameters: handshake.TransportParameters{
|
||||
OriginalConnectionID: protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad},
|
||||
StatelessResetToken: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
|
||||
},
|
||||
}
|
||||
_, err := sess.processTransportParametersForClient(eetp.Marshal())
|
||||
Expect(err).To(MatchError("expected original_connection_id to equal 0xdeadbeef, is 0xdecafbad"))
|
||||
})
|
||||
|
||||
Context("Version Negotiation", func() {
|
||||
var params handshake.TransportParameters
|
||||
|
||||
BeforeEach(func() {
|
||||
params = handshake.TransportParameters{
|
||||
StatelessResetToken: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
|
||||
OriginalConnectionID: sess.origDestConnID,
|
||||
}
|
||||
})
|
||||
|
||||
It("accepts a valid version negotiation", func() {
|
||||
sess.initialVersion = 13
|
||||
sess.version = 37
|
||||
sess.config.Versions = []protocol.VersionNumber{13, 37, 42}
|
||||
eetp := &handshake.EncryptedExtensionsTransportParameters{
|
||||
NegotiatedVersion: 37,
|
||||
SupportedVersions: []protocol.VersionNumber{36, 37, 38},
|
||||
Parameters: params,
|
||||
}
|
||||
_, err := sess.processTransportParametersForClient(eetp.Marshal())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("errors if the current version doesn't match negotiated_version", func() {
|
||||
sess.initialVersion = 13
|
||||
sess.version = 37
|
||||
sess.config.Versions = []protocol.VersionNumber{13, 37, 42}
|
||||
eetp := &handshake.EncryptedExtensionsTransportParameters{
|
||||
NegotiatedVersion: 38,
|
||||
SupportedVersions: []protocol.VersionNumber{36, 37, 38},
|
||||
Parameters: params,
|
||||
}
|
||||
_, err := sess.processTransportParametersForClient(eetp.Marshal())
|
||||
Expect(err).To(MatchError("VersionNegotiationMismatch: current version doesn't match negotiated_version"))
|
||||
})
|
||||
|
||||
It("errors if the current version is not contained in the server's supported versions", func() {
|
||||
sess.version = 42
|
||||
eetp := &handshake.EncryptedExtensionsTransportParameters{
|
||||
NegotiatedVersion: 42,
|
||||
SupportedVersions: []protocol.VersionNumber{43, 44},
|
||||
Parameters: params,
|
||||
}
|
||||
_, err := sess.processTransportParametersForClient(eetp.Marshal())
|
||||
Expect(err).To(MatchError("VersionNegotiationMismatch: current version not included in the supported versions"))
|
||||
})
|
||||
|
||||
It("errors if version negotiation was performed, but would have picked a different version based on the supported version list", func() {
|
||||
sess.version = 42
|
||||
sess.initialVersion = 41
|
||||
sess.config.Versions = []protocol.VersionNumber{43, 42, 41}
|
||||
serverSupportedVersions := []protocol.VersionNumber{42, 43}
|
||||
// check that version negotiation would have led us to pick version 43
|
||||
ver, ok := protocol.ChooseSupportedVersion(sess.config.Versions, serverSupportedVersions)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(ver).To(Equal(protocol.VersionNumber(43)))
|
||||
eetp := &handshake.EncryptedExtensionsTransportParameters{
|
||||
NegotiatedVersion: 42,
|
||||
SupportedVersions: serverSupportedVersions,
|
||||
Parameters: params,
|
||||
}
|
||||
_, err := sess.processTransportParametersForClient(eetp.Marshal())
|
||||
Expect(err).To(MatchError("VersionNegotiationMismatch: would have picked a different version"))
|
||||
})
|
||||
|
||||
It("doesn't error if it would have picked a different version based on the supported version list, if no version negotiation was performed", func() {
|
||||
sess.version = 42
|
||||
sess.initialVersion = 42 // version == initialVersion means no version negotiation was performed
|
||||
sess.config.Versions = []protocol.VersionNumber{43, 42, 41}
|
||||
serverSupportedVersions := []protocol.VersionNumber{42, 43}
|
||||
// check that version negotiation would have led us to pick version 43
|
||||
ver, ok := protocol.ChooseSupportedVersion(sess.config.Versions, serverSupportedVersions)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(ver).To(Equal(protocol.VersionNumber(43)))
|
||||
eetp := &handshake.EncryptedExtensionsTransportParameters{
|
||||
NegotiatedVersion: 42,
|
||||
SupportedVersions: serverSupportedVersions,
|
||||
Parameters: params,
|
||||
}
|
||||
_, err := sess.processTransportParametersForClient(eetp.Marshal())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user