separate connection parameters negotiation and gQUIC handshake parsing

This commit is contained in:
Marten Seemann 2017-09-25 18:48:15 +07:00
parent 95901cdee4
commit ebb4150e63
10 changed files with 289 additions and 317 deletions

View file

@ -0,0 +1,149 @@
package handshake
import (
"sync"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
)
// ConnectionParametersManager negotiates and stores the connection parameters.
// A ConnectionParametersManager can be used for a server as well as a client.
type ConnectionParametersManager interface {
GetSendStreamFlowControlWindow() protocol.ByteCount
GetSendConnectionFlowControlWindow() protocol.ByteCount
GetReceiveStreamFlowControlWindow() protocol.ByteCount
GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount
GetReceiveConnectionFlowControlWindow() protocol.ByteCount
GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount
GetMaxOutgoingStreams() uint32
GetMaxIncomingStreams() uint32
GetIdleConnectionStateLifetime() time.Duration
// determines if the client requests truncated ConnectionIDs.
// It always returns false for the server.
TruncateConnectionID() bool
}
// For the server:
// 1. call SetFromMap with the values received in the CHLO. This sets the corresponding values here, subject to negotiation
// 2. call GetHelloMap to get the values to send in the SHLO
// For the client:
// 1. call GetHelloMap to get the values to send in a CHLO
// 2. call SetFromMap with the values received in the SHLO
type baseConnectionParametersManager struct {
mutex sync.RWMutex
version protocol.VersionNumber
perspective protocol.Perspective
flowControlNegotiated bool
truncateConnectionID bool
maxStreamsPerConnection uint32
maxIncomingDynamicStreamsPerConnection uint32
idleConnectionStateLifetime time.Duration
sendStreamFlowControlWindow protocol.ByteCount
sendConnectionFlowControlWindow protocol.ByteCount
receiveStreamFlowControlWindow protocol.ByteCount
receiveConnectionFlowControlWindow protocol.ByteCount
maxReceiveStreamFlowControlWindow protocol.ByteCount
maxReceiveConnectionFlowControlWindow protocol.ByteCount
}
func (h *baseConnectionParametersManager) init(params *TransportParameters) {
h.sendStreamFlowControlWindow = protocol.InitialStreamFlowControlWindow // can only be changed by the client
h.sendConnectionFlowControlWindow = protocol.InitialConnectionFlowControlWindow // can only be changed by the client
h.receiveStreamFlowControlWindow = protocol.ReceiveStreamFlowControlWindow
h.receiveConnectionFlowControlWindow = protocol.ReceiveConnectionFlowControlWindow
h.maxReceiveStreamFlowControlWindow = params.MaxReceiveStreamFlowControlWindow
h.maxReceiveConnectionFlowControlWindow = params.MaxReceiveConnectionFlowControlWindow
h.idleConnectionStateLifetime = params.IdleTimeout
if h.perspective == protocol.PerspectiveServer {
h.maxStreamsPerConnection = protocol.MaxStreamsPerConnection // this is the value negotiated based on what the client sent
h.maxIncomingDynamicStreamsPerConnection = protocol.MaxStreamsPerConnection // "incoming" seen from the client's perspective
} else {
h.maxStreamsPerConnection = protocol.MaxStreamsPerConnection // this is the value negotiated based on what the client sent
h.maxIncomingDynamicStreamsPerConnection = protocol.MaxStreamsPerConnection // "incoming" seen from the server's perspective
}
}
func (h *baseConnectionParametersManager) negotiateMaxStreamsPerConnection(clientValue uint32) uint32 {
return utils.MinUint32(clientValue, protocol.MaxStreamsPerConnection)
}
func (h *baseConnectionParametersManager) negotiateMaxIncomingDynamicStreamsPerConnection(clientValue uint32) uint32 {
return utils.MinUint32(clientValue, protocol.MaxIncomingDynamicStreamsPerConnection)
}
func (h *baseConnectionParametersManager) negotiateIdleConnectionStateLifetime(clientValue time.Duration) time.Duration {
return utils.MinDuration(clientValue, h.idleConnectionStateLifetime)
}
// GetSendStreamFlowControlWindow gets the size of the stream-level flow control window for sending data
func (h *baseConnectionParametersManager) GetSendStreamFlowControlWindow() protocol.ByteCount {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.sendStreamFlowControlWindow
}
// GetSendConnectionFlowControlWindow gets the size of the stream-level flow control window for sending data
func (h *baseConnectionParametersManager) GetSendConnectionFlowControlWindow() protocol.ByteCount {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.sendConnectionFlowControlWindow
}
func (h *baseConnectionParametersManager) GetReceiveStreamFlowControlWindow() protocol.ByteCount {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.receiveStreamFlowControlWindow
}
// GetMaxReceiveStreamFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
func (h *baseConnectionParametersManager) GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount {
return h.maxReceiveStreamFlowControlWindow
}
// GetReceiveConnectionFlowControlWindow gets the size of the stream-level flow control window for receiving data
func (h *baseConnectionParametersManager) GetReceiveConnectionFlowControlWindow() protocol.ByteCount {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.receiveConnectionFlowControlWindow
}
func (h *baseConnectionParametersManager) GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount {
return h.maxReceiveConnectionFlowControlWindow
}
func (h *baseConnectionParametersManager) GetMaxOutgoingStreams() uint32 {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.maxIncomingDynamicStreamsPerConnection
}
func (h *baseConnectionParametersManager) GetMaxIncomingStreams() uint32 {
h.mutex.RLock()
defer h.mutex.RUnlock()
maxStreams := protocol.MaxIncomingDynamicStreamsPerConnection
return utils.MaxUint32(uint32(maxStreams)+protocol.MaxStreamsMinimumIncrement, uint32(float64(maxStreams)*protocol.MaxStreamsMultiplier))
}
func (h *baseConnectionParametersManager) GetIdleConnectionStateLifetime() time.Duration {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.idleConnectionStateLifetime
}
func (h *baseConnectionParametersManager) TruncateConnectionID() bool {
if h.perspective == protocol.PerspectiveClient {
return false
}
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.truncateConnectionID
}

View file

@ -1,262 +0,0 @@
package handshake
import (
"bytes"
"sync"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/qerr"
)
// ConnectionParametersManager negotiates and stores the connection parameters
// A ConnectionParametersManager can be used for a server as well as a client
// For the server:
// 1. call SetFromMap with the values received in the CHLO. This sets the corresponding values here, subject to negotiation
// 2. call GetHelloMap to get the values to send in the SHLO
// For the client:
// 1. call GetHelloMap to get the values to send in a CHLO
// 2. call SetFromMap with the values received in the SHLO
type ConnectionParametersManager interface {
SetFromMap(map[Tag][]byte) error
GetHelloMap() (map[Tag][]byte, error)
GetSendStreamFlowControlWindow() protocol.ByteCount
GetSendConnectionFlowControlWindow() protocol.ByteCount
GetReceiveStreamFlowControlWindow() protocol.ByteCount
GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount
GetReceiveConnectionFlowControlWindow() protocol.ByteCount
GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount
GetMaxOutgoingStreams() uint32
GetMaxIncomingStreams() uint32
GetIdleConnectionStateLifetime() time.Duration
TruncateConnectionID() bool
}
type connectionParametersManager struct {
mutex sync.RWMutex
version protocol.VersionNumber
perspective protocol.Perspective
flowControlNegotiated bool
truncateConnectionID bool
maxStreamsPerConnection uint32
maxIncomingDynamicStreamsPerConnection uint32
idleConnectionStateLifetime time.Duration
sendStreamFlowControlWindow protocol.ByteCount
sendConnectionFlowControlWindow protocol.ByteCount
receiveStreamFlowControlWindow protocol.ByteCount
receiveConnectionFlowControlWindow protocol.ByteCount
maxReceiveStreamFlowControlWindow protocol.ByteCount
maxReceiveConnectionFlowControlWindow protocol.ByteCount
}
var _ ConnectionParametersManager = &connectionParametersManager{}
// ErrMalformedTag is returned when the tag value cannot be read
var (
ErrMalformedTag = qerr.Error(qerr.InvalidCryptoMessageParameter, "malformed Tag value")
ErrFlowControlRenegotiationNotSupported = qerr.Error(qerr.InvalidCryptoMessageParameter, "renegotiation of flow control parameters not supported")
)
// NewConnectionParamatersManager creates a new connection parameters manager
func NewConnectionParamatersManager(
pers protocol.Perspective,
v protocol.VersionNumber,
params *TransportParameters,
) ConnectionParametersManager {
h := &connectionParametersManager{
perspective: pers,
version: v,
sendStreamFlowControlWindow: protocol.InitialStreamFlowControlWindow, // can only be changed by the client
sendConnectionFlowControlWindow: protocol.InitialConnectionFlowControlWindow, // can only be changed by the client
receiveStreamFlowControlWindow: protocol.ReceiveStreamFlowControlWindow,
receiveConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
maxReceiveStreamFlowControlWindow: params.MaxReceiveStreamFlowControlWindow,
maxReceiveConnectionFlowControlWindow: params.MaxReceiveConnectionFlowControlWindow,
}
h.idleConnectionStateLifetime = params.IdleTimeout
if h.perspective == protocol.PerspectiveServer {
h.maxStreamsPerConnection = protocol.MaxStreamsPerConnection // this is the value negotiated based on what the client sent
h.maxIncomingDynamicStreamsPerConnection = protocol.MaxStreamsPerConnection // "incoming" seen from the client's perspective
} else {
h.maxStreamsPerConnection = protocol.MaxStreamsPerConnection // this is the value negotiated based on what the client sent
h.maxIncomingDynamicStreamsPerConnection = protocol.MaxStreamsPerConnection // "incoming" seen from the server's perspective
}
return h
}
// SetFromMap reads all params
func (h *connectionParametersManager) SetFromMap(params map[Tag][]byte) error {
h.mutex.Lock()
defer h.mutex.Unlock()
if value, ok := params[TagTCID]; ok && h.perspective == protocol.PerspectiveServer {
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
h.truncateConnectionID = (clientValue == 0)
}
if value, ok := params[TagMSPC]; ok {
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
h.maxStreamsPerConnection = h.negotiateMaxStreamsPerConnection(clientValue)
}
if value, ok := params[TagMIDS]; ok {
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
h.maxIncomingDynamicStreamsPerConnection = h.negotiateMaxIncomingDynamicStreamsPerConnection(clientValue)
}
if value, ok := params[TagICSL]; ok {
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
h.idleConnectionStateLifetime = h.negotiateIdleConnectionStateLifetime(time.Duration(clientValue) * time.Second)
}
if value, ok := params[TagSFCW]; ok {
if h.flowControlNegotiated {
return ErrFlowControlRenegotiationNotSupported
}
sendStreamFlowControlWindow, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
h.sendStreamFlowControlWindow = protocol.ByteCount(sendStreamFlowControlWindow)
}
if value, ok := params[TagCFCW]; ok {
if h.flowControlNegotiated {
return ErrFlowControlRenegotiationNotSupported
}
sendConnectionFlowControlWindow, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
h.sendConnectionFlowControlWindow = protocol.ByteCount(sendConnectionFlowControlWindow)
}
_, containsSFCW := params[TagSFCW]
_, containsCFCW := params[TagCFCW]
if containsCFCW || containsSFCW {
h.flowControlNegotiated = true
}
return nil
}
func (h *connectionParametersManager) negotiateMaxStreamsPerConnection(clientValue uint32) uint32 {
return utils.MinUint32(clientValue, protocol.MaxStreamsPerConnection)
}
func (h *connectionParametersManager) negotiateMaxIncomingDynamicStreamsPerConnection(clientValue uint32) uint32 {
return utils.MinUint32(clientValue, protocol.MaxIncomingDynamicStreamsPerConnection)
}
func (h *connectionParametersManager) negotiateIdleConnectionStateLifetime(clientValue time.Duration) time.Duration {
return utils.MinDuration(clientValue, h.idleConnectionStateLifetime)
}
// GetHelloMap gets all parameters needed for the Hello message
func (h *connectionParametersManager) GetHelloMap() (map[Tag][]byte, error) {
sfcw := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(sfcw, uint32(h.GetReceiveStreamFlowControlWindow()))
cfcw := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(cfcw, uint32(h.GetReceiveConnectionFlowControlWindow()))
mspc := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(mspc, h.maxStreamsPerConnection)
mids := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(mids, protocol.MaxIncomingDynamicStreamsPerConnection)
icsl := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(icsl, uint32(h.GetIdleConnectionStateLifetime()/time.Second))
return map[Tag][]byte{
TagICSL: icsl.Bytes(),
TagMSPC: mspc.Bytes(),
TagMIDS: mids.Bytes(),
TagCFCW: cfcw.Bytes(),
TagSFCW: sfcw.Bytes(),
}, nil
}
// GetSendStreamFlowControlWindow gets the size of the stream-level flow control window for sending data
func (h *connectionParametersManager) GetSendStreamFlowControlWindow() protocol.ByteCount {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.sendStreamFlowControlWindow
}
// GetSendConnectionFlowControlWindow gets the size of the stream-level flow control window for sending data
func (h *connectionParametersManager) GetSendConnectionFlowControlWindow() protocol.ByteCount {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.sendConnectionFlowControlWindow
}
// GetReceiveStreamFlowControlWindow gets the size of the stream-level flow control window for receiving data
func (h *connectionParametersManager) GetReceiveStreamFlowControlWindow() protocol.ByteCount {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.receiveStreamFlowControlWindow
}
// GetMaxReceiveStreamFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
func (h *connectionParametersManager) GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount {
return h.maxReceiveStreamFlowControlWindow
}
// GetReceiveConnectionFlowControlWindow gets the size of the stream-level flow control window for receiving data
func (h *connectionParametersManager) GetReceiveConnectionFlowControlWindow() protocol.ByteCount {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.receiveConnectionFlowControlWindow
}
// GetMaxReceiveConnectionFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
func (h *connectionParametersManager) GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount {
return h.maxReceiveConnectionFlowControlWindow
}
// GetMaxOutgoingStreams gets the maximum number of outgoing streams per connection
func (h *connectionParametersManager) GetMaxOutgoingStreams() uint32 {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.maxIncomingDynamicStreamsPerConnection
}
// GetMaxIncomingStreams get the maximum number of incoming streams per connection
func (h *connectionParametersManager) GetMaxIncomingStreams() uint32 {
h.mutex.RLock()
defer h.mutex.RUnlock()
maxStreams := protocol.MaxIncomingDynamicStreamsPerConnection
return utils.MaxUint32(uint32(maxStreams)+protocol.MaxStreamsMinimumIncrement, uint32(float64(maxStreams)*protocol.MaxStreamsMultiplier))
}
// GetIdleConnectionStateLifetime gets the idle timeout
func (h *connectionParametersManager) GetIdleConnectionStateLifetime() time.Duration {
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.idleConnectionStateLifetime
}
// TruncateConnectionID determines if the client requests truncated ConnectionIDs
func (h *connectionParametersManager) TruncateConnectionID() bool {
if h.perspective == protocol.PerspectiveClient {
return false
}
h.mutex.RLock()
defer h.mutex.RUnlock()
return h.truncateConnectionID
}

View file

@ -52,7 +52,7 @@ type cryptoSetupClient struct {
aeadChanged chan<- protocol.EncryptionLevel
requestConnIDTruncation bool
connectionParameters ConnectionParametersManager
connectionParameters *gquicConnectionParametersManager
}
var _ CryptoSetup = &cryptoSetupClient{}
@ -73,7 +73,7 @@ func NewCryptoSetupClient(
aeadChanged chan<- protocol.EncryptionLevel,
negotiatedVersions []protocol.VersionNumber,
) (CryptoSetup, ConnectionParametersManager, error) {
cpm := NewConnectionParamatersManager(protocol.PerspectiveClient, version, params)
cpm := newGQUICConnectionParamatersManager(protocol.PerspectiveClient, version, params)
return &cryptoSetupClient{
hostname: hostname,
connID: connID,

View file

@ -47,7 +47,7 @@ type cryptoSetupServer struct {
cryptoStream io.ReadWriter
connectionParameters ConnectionParametersManager
connectionParameters *gquicConnectionParametersManager
mutex sync.RWMutex
}
@ -79,7 +79,7 @@ func NewCryptoSetup(
return nil, nil, err
}
cpm := NewConnectionParamatersManager(protocol.PerspectiveServer, version, params)
cpm := newGQUICConnectionParamatersManager(protocol.PerspectiveServer, version, params)
return &cryptoSetupServer{
connID: connID,
remoteAddr: remoteAddr,

View file

@ -47,13 +47,14 @@ func NewCryptoSetupTLS(
}
mintConf.ServerName = hostname
// TODO: implement connection paramaters negotiation for TLS
return &cryptoSetupTLS{
perspective: perspective,
mintConf: mintConf,
nullAEAD: crypto.NewNullAEAD(perspective, version),
keyDerivation: crypto.DeriveAESKeys,
aeadChanged: aeadChanged,
}, NewConnectionParamatersManager(perspective, version, &TransportParameters{IdleTimeout: protocol.DefaultIdleTimeout}), nil
}, newGQUICConnectionParamatersManager(perspective, version, &TransportParameters{IdleTimeout: protocol.DefaultIdleTimeout}), nil
}
func (h *cryptoSetupTLS) HandleCryptoStream(cryptoStream io.ReadWriter) error {

View file

@ -0,0 +1,116 @@
package handshake
import (
"bytes"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/qerr"
)
var _ ConnectionParametersManager = &baseConnectionParametersManager{}
// errMalformedTag is returned when the tag value cannot be read
var (
errMalformedTag = qerr.Error(qerr.InvalidCryptoMessageParameter, "malformed Tag value")
errFlowControlRenegotiationNotSupported = qerr.Error(qerr.InvalidCryptoMessageParameter, "renegotiation of flow control parameters not supported")
)
type gquicConnectionParametersManager struct {
baseConnectionParametersManager
}
// newConnectionParamatersManager creates a new connection parameters manager
func newGQUICConnectionParamatersManager(pers protocol.Perspective, v protocol.VersionNumber, params *TransportParameters) *gquicConnectionParametersManager {
h := &gquicConnectionParametersManager{}
h.perspective = pers
h.version = v
h.init(params)
return h
}
// SetFromMap reads all params.
func (h *gquicConnectionParametersManager) SetFromMap(params map[Tag][]byte) error {
h.mutex.Lock()
defer h.mutex.Unlock()
if value, ok := params[TagTCID]; ok && h.perspective == protocol.PerspectiveServer {
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return errMalformedTag
}
h.truncateConnectionID = (clientValue == 0)
}
if value, ok := params[TagMSPC]; ok {
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return errMalformedTag
}
h.maxStreamsPerConnection = h.negotiateMaxStreamsPerConnection(clientValue)
}
if value, ok := params[TagMIDS]; ok {
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return errMalformedTag
}
h.maxIncomingDynamicStreamsPerConnection = h.negotiateMaxIncomingDynamicStreamsPerConnection(clientValue)
}
if value, ok := params[TagICSL]; ok {
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return errMalformedTag
}
h.idleConnectionStateLifetime = h.negotiateIdleConnectionStateLifetime(time.Duration(clientValue) * time.Second)
}
if value, ok := params[TagSFCW]; ok {
if h.flowControlNegotiated {
return errFlowControlRenegotiationNotSupported
}
sendStreamFlowControlWindow, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return errMalformedTag
}
h.sendStreamFlowControlWindow = protocol.ByteCount(sendStreamFlowControlWindow)
}
if value, ok := params[TagCFCW]; ok {
if h.flowControlNegotiated {
return errFlowControlRenegotiationNotSupported
}
sendConnectionFlowControlWindow, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return errMalformedTag
}
h.sendConnectionFlowControlWindow = protocol.ByteCount(sendConnectionFlowControlWindow)
}
_, containsSFCW := params[TagSFCW]
_, containsCFCW := params[TagCFCW]
if containsCFCW || containsSFCW {
h.flowControlNegotiated = true
}
return nil
}
// GetHelloMap gets all parameters needed for the Hello message.
func (h *gquicConnectionParametersManager) GetHelloMap() (map[Tag][]byte, error) {
sfcw := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(sfcw, uint32(h.GetReceiveStreamFlowControlWindow()))
cfcw := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(cfcw, uint32(h.GetReceiveConnectionFlowControlWindow()))
mspc := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(mspc, h.maxStreamsPerConnection)
mids := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(mids, protocol.MaxIncomingDynamicStreamsPerConnection)
icsl := bytes.NewBuffer([]byte{})
utils.LittleEndian.WriteUint32(icsl, uint32(h.GetIdleConnectionStateLifetime()/time.Second))
return map[Tag][]byte{
TagICSL: icsl.Bytes(),
TagMSPC: mspc.Bytes(),
TagMIDS: mids.Bytes(),
TagCFCW: cfcw.Bytes(),
TagSFCW: sfcw.Bytes(),
}, nil
}

View file

@ -11,8 +11,8 @@ import (
)
var _ = Describe("ConnectionsParameterManager", func() {
var cpm *connectionParametersManager // a connectionParametersManager for a server
var cpmClient *connectionParametersManager
var cpm *gquicConnectionParametersManager // a connectionParametersManager for a server
var cpmClient *gquicConnectionParametersManager
const MB = 1 << 20
maxReceiveStreamFlowControlWindowServer := protocol.ByteCount(math.Floor(1.1 * MB)) // default is 1 MB
maxReceiveConnectionFlowControlWindowServer := protocol.ByteCount(math.Floor(1.5 * MB)) // default is 1.5 MB
@ -20,7 +20,7 @@ var _ = Describe("ConnectionsParameterManager", func() {
maxReceiveConnectionFlowControlWindowClient := protocol.ByteCount(math.Floor(13 * MB)) // default is 15 MB
idleTimeout := 42 * time.Second
BeforeEach(func() {
cpm = NewConnectionParamatersManager(
cpm = newGQUICConnectionParamatersManager(
protocol.PerspectiveServer,
protocol.VersionWhatever,
&TransportParameters{
@ -28,8 +28,8 @@ var _ = Describe("ConnectionsParameterManager", func() {
MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindowServer,
IdleTimeout: idleTimeout,
},
).(*connectionParametersManager)
cpmClient = NewConnectionParamatersManager(
)
cpmClient = newGQUICConnectionParamatersManager(
protocol.PerspectiveClient,
protocol.VersionWhatever,
&TransportParameters{
@ -37,7 +37,7 @@ var _ = Describe("ConnectionsParameterManager", func() {
MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindowClient,
IdleTimeout: idleTimeout,
},
).(*connectionParametersManager)
)
})
Context("SHLO", func() {
@ -139,7 +139,7 @@ var _ = Describe("ConnectionsParameterManager", func() {
It("errors when given an invalid value", func() {
values := map[Tag][]byte{TagTCID: {2, 0, 0}} // 1 byte too short
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(err).To(MatchError(errMalformedTag))
})
})
@ -175,7 +175,7 @@ var _ = Describe("ConnectionsParameterManager", func() {
It("does not change the stream-level flow control window when given an invalid value", func() {
values := map[Tag][]byte{TagSFCW: {0xDE, 0xAD, 0xBE}} // 1 byte too short
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(err).To(MatchError(errMalformedTag))
Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.InitialStreamFlowControlWindow))
})
@ -189,7 +189,7 @@ var _ = Describe("ConnectionsParameterManager", func() {
It("does not change the connection-level flow control window when given an invalid value", func() {
values := map[Tag][]byte{TagCFCW: {0xDE, 0xAD, 0xBE}} // 1 byte too short
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(err).To(MatchError(errMalformedTag))
Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.InitialConnectionFlowControlWindow))
})
@ -205,7 +205,7 @@ var _ = Describe("ConnectionsParameterManager", func() {
TagSFCW: {0x13, 0x37, 0x13, 0x37},
}
err = cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrFlowControlRenegotiationNotSupported))
Expect(err).To(MatchError(errFlowControlRenegotiationNotSupported))
Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.ByteCount(0xEFBEADDE)))
Expect(cpm.GetSendConnectionFlowControlWindow()).To(Equal(protocol.ByteCount(0xEFBEADDE)))
})
@ -239,7 +239,7 @@ var _ = Describe("ConnectionsParameterManager", func() {
TagSFCW: {0xDE, 0xAD, 0xBE}, // 1 byte too short
}
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(err).To(MatchError(errMalformedTag))
Expect(cpm.GetIdleConnectionStateLifetime()).To(Equal(idleTimeout))
})
@ -252,7 +252,7 @@ var _ = Describe("ConnectionsParameterManager", func() {
It("errors when given an invalid value", func() {
values := map[Tag][]byte{TagICSL: {2, 0, 0}} // 1 byte too short
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(err).To(MatchError(errMalformedTag))
})
})
@ -260,13 +260,13 @@ var _ = Describe("ConnectionsParameterManager", func() {
It("errors when given an invalid max streams per connection value", func() {
values := map[Tag][]byte{TagMSPC: {2, 0, 0}} // 1 byte too short
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(err).To(MatchError(errMalformedTag))
})
It("errors when given an invalid max dynamic incoming streams per connection value", func() {
values := map[Tag][]byte{TagMIDS: {2, 0, 0}} // 1 byte too short
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(err).To(MatchError(errMalformedTag))
})
Context("outgoing connections", func() {

View file

@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: ../handshake/connection_parameters_manager.go
// Source: ../handshake/base_connection_parameters_manager.go
package mocks
@ -8,7 +8,6 @@ import (
time "time"
gomock "github.com/golang/mock/gomock"
"github.com/lucas-clemente/quic-go/internal/handshake"
protocol "github.com/lucas-clemente/quic-go/internal/protocol"
)
@ -35,31 +34,6 @@ func (_m *MockConnectionParametersManager) EXPECT() *MockConnectionParametersMan
return _m.recorder
}
// SetFromMap mocks base method
func (_m *MockConnectionParametersManager) SetFromMap(_param0 map[handshake.Tag][]byte) error {
ret := _m.ctrl.Call(_m, "SetFromMap", _param0)
ret0, _ := ret[0].(error)
return ret0
}
// SetFromMap indicates an expected call of SetFromMap
func (_mr *MockConnectionParametersManagerMockRecorder) SetFromMap(arg0 interface{}) *gomock.Call {
return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "SetFromMap", reflect.TypeOf((*MockConnectionParametersManager)(nil).SetFromMap), arg0)
}
// GetHelloMap mocks base method
func (_m *MockConnectionParametersManager) GetHelloMap() (map[handshake.Tag][]byte, error) {
ret := _m.ctrl.Call(_m, "GetHelloMap")
ret0, _ := ret[0].(map[handshake.Tag][]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetHelloMap indicates an expected call of GetHelloMap
func (_mr *MockConnectionParametersManagerMockRecorder) GetHelloMap() *gomock.Call {
return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetHelloMap", reflect.TypeOf((*MockConnectionParametersManager)(nil).GetHelloMap))
}
// GetSendStreamFlowControlWindow mocks base method
func (_m *MockConnectionParametersManager) GetSendStreamFlowControlWindow() protocol.ByteCount {
ret := _m.ctrl.Call(_m, "GetSendStreamFlowControlWindow")

View file

@ -4,5 +4,5 @@ package mocks
// so we have to use sed to correct for that
//go:generate sh -c "mockgen -package mocks_fc -source ../flowcontrol/interface.go | sed \"s/\\[\\]WindowUpdate/[]flowcontrol.WindowUpdate/g\" > mocks_fc/flow_control_manager.go"
//go:generate sh -c "mockgen -package mocks -source ../handshake/connection_parameters_manager.go | sed \"s/\\[Tag\\]/[handshake.Tag]/g\" > cpm.go"
//go:generate sh -c "mockgen -package mocks -source ../handshake/base_connection_parameters_manager.go > cpm.go"
//go:generate sh -c "goimports -w ."

View file

@ -143,15 +143,9 @@ func areSessionsRunning() bool {
return strings.Contains(b.String(), "quic-go.(*session).run")
}
type mockConnectionParametersManager struct {
}
type mockConnectionParametersManager struct{}
func (m *mockConnectionParametersManager) SetFromMap(map[handshake.Tag][]byte) error {
panic("not implement")
}
func (m *mockConnectionParametersManager) GetHelloMap() (map[handshake.Tag][]byte, error) {
panic("not implement")
}
var _ handshake.ConnectionParametersManager = &mockConnectionParametersManager{}
func (m *mockConnectionParametersManager) GetSendStreamFlowControlWindow() protocol.ByteCount {
return protocol.InitialStreamFlowControlWindow