diff --git a/handshake/connection_parameters_manager.go b/handshake/connection_parameters_manager.go index 5d294815..208082ce 100644 --- a/handshake/connection_parameters_manager.go +++ b/handshake/connection_parameters_manager.go @@ -19,6 +19,8 @@ type ConnectionParametersManager struct { params map[Tag][]byte mutex sync.RWMutex + flowControlNegotiated bool // have the flow control parameters for sending already been negotiated + maxStreamsPerConnection uint32 idleConnectionStateLifetime time.Duration sendStreamFlowControlWindow protocol.ByteCount @@ -30,7 +32,10 @@ type ConnectionParametersManager struct { var errTagNotInConnectionParameterMap = errors.New("ConnectionParametersManager: Tag not found in ConnectionsParameter map") // ErrMalformedTag is returned when the tag value cannot be read -var ErrMalformedTag = qerr.Error(qerr.InvalidCryptoMessageParameter, "malformed Tag value") +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() *ConnectionParametersManager { @@ -66,12 +71,18 @@ func (h *ConnectionParametersManager) SetFromMap(params map[Tag][]byte) error { } h.idleConnectionStateLifetime = h.negotiateIdleConnectionStateLifetime(time.Duration(clientValue) * time.Second) case TagSFCW: + if h.flowControlNegotiated { + return ErrFlowControlRenegotiationNotSupported + } sendStreamFlowControlWindow, err := utils.ReadUint32(bytes.NewBuffer(value)) if err != nil { return ErrMalformedTag } h.sendStreamFlowControlWindow = protocol.ByteCount(sendStreamFlowControlWindow) case TagCFCW: + if h.flowControlNegotiated { + return ErrFlowControlRenegotiationNotSupported + } sendConnectionFlowControlWindow, err := utils.ReadUint32(bytes.NewBuffer(value)) if err != nil { return ErrMalformedTag @@ -80,6 +91,12 @@ func (h *ConnectionParametersManager) SetFromMap(params map[Tag][]byte) error { } } + _, containsSFCW := params[TagSFCW] + _, containsCFCW := params[TagCFCW] + if containsCFCW || containsSFCW { + h.flowControlNegotiated = true + } + return nil } diff --git a/handshake/connection_parameters_manager_test.go b/handshake/connection_parameters_manager_test.go index 6a1da498..d3f8ec85 100644 --- a/handshake/connection_parameters_manager_test.go +++ b/handshake/connection_parameters_manager_test.go @@ -134,6 +134,23 @@ var _ = Describe("ConnectionsParameterManager", func() { Expect(err).To(MatchError(ErrMalformedTag)) Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.InitialConnectionFlowControlWindow)) }) + + It("does not allow renegotiation of flow control parameters", func() { + values := map[Tag][]byte{ + TagCFCW: {0xDE, 0xAD, 0xBE, 0xEF}, + TagSFCW: {0xDE, 0xAD, 0xBE, 0xEF}, + } + err := cpm.SetFromMap(values) + Expect(err).ToNot(HaveOccurred()) + values = map[Tag][]byte{ + TagCFCW: {0x13, 0x37, 0x13, 0x37}, + TagSFCW: {0x13, 0x37, 0x13, 0x37}, + } + err = cpm.SetFromMap(values) + Expect(err).To(MatchError(ErrFlowControlRenegotiationNotSupported)) + Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.ByteCount(0xEFBEADDE))) + Expect(cpm.GetSendConnectionFlowControlWindow()).To(Equal(protocol.ByteCount(0xEFBEADDE))) + }) }) Context("idle connection state lifetime", func() {