don't negotiate the maximum incoming streams value

The maximum number of incoming streams doesn't need to be negotiated. It
is a value that is only announced by the peer, and has to be respected.
Furthermore, Chrome doesn't seem to care about the MSPC value anymore
(since MIDS was introduced), so there's no need to send this in the
handshake any more.
This commit is contained in:
Marten Seemann
2017-10-15 09:23:42 +08:00
parent a816d5a12e
commit daff6256b9
7 changed files with 19 additions and 87 deletions

View File

@@ -16,7 +16,6 @@ type ParamsNegotiator interface {
GetReceiveStreamFlowControlWindow() protocol.ByteCount
GetReceiveConnectionFlowControlWindow() protocol.ByteCount
GetMaxOutgoingStreams() uint32
GetMaxIncomingStreams() uint32
// get the idle timeout that was sent by the peer
GetRemoteIdleTimeout() time.Duration
// determines if the client requests omission of connection IDs.
@@ -40,7 +39,6 @@ type paramsNegotiatorBase struct {
omitConnectionID bool
requestConnectionIDOmission bool
maxStreamsPerConnection uint32
maxIncomingDynamicStreamsPerConnection uint32
idleTimeout time.Duration
remoteIdleTimeout time.Duration
@@ -59,18 +57,12 @@ func (h *paramsNegotiatorBase) init(params *TransportParameters) {
h.idleTimeout = 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 *paramsNegotiatorBase) negotiateMaxStreamsPerConnection(clientValue uint32) uint32 {
return utils.MinUint32(clientValue, protocol.MaxStreamsPerConnection)
}
func (h *paramsNegotiatorBase) negotiateMaxIncomingDynamicStreamsPerConnection(clientValue uint32) uint32 {
return utils.MinUint32(clientValue, protocol.MaxIncomingDynamicStreamsPerConnection)
}
@@ -109,14 +101,6 @@ func (h *paramsNegotiatorBase) GetMaxOutgoingStreams() uint32 {
return h.maxIncomingDynamicStreamsPerConnection
}
func (h *paramsNegotiatorBase) 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 *paramsNegotiatorBase) setRemoteIdleTimeout(t time.Duration) {
h.remoteIdleTimeout = utils.MaxDuration(protocol.MinRemoteIdleTimeout, t)
}

View File

@@ -42,13 +42,6 @@ func (h *paramsNegotiatorGQUIC) SetFromMap(params map[Tag][]byte) error {
}
h.omitConnectionID = (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 {
@@ -99,8 +92,6 @@ func (h *paramsNegotiatorGQUIC) GetHelloMap() (map[Tag][]byte, error) {
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{})
@@ -108,7 +99,6 @@ func (h *paramsNegotiatorGQUIC) GetHelloMap() (map[Tag][]byte, error) {
return map[Tag][]byte{
TagICSL: icsl.Bytes(),
TagMSPC: mspc.Bytes(),
TagMIDS: mids.Bytes(),
TagCFCW: cfcw.Bytes(),
TagSFCW: sfcw.Bytes(),

View File

@@ -40,7 +40,6 @@ var _ = Describe("Params Negotiator (for gQUIC)", func() {
entryMap, err := pn.GetHelloMap()
Expect(err).ToNot(HaveOccurred())
Expect(entryMap).To(HaveKey(TagICSL))
Expect(entryMap).To(HaveKey(TagMSPC))
Expect(entryMap).To(HaveKey(TagMIDS))
})
@@ -68,16 +67,6 @@ var _ = Describe("Params Negotiator (for gQUIC)", func() {
Expect(entryMap[TagICSL]).To(Equal([]byte{0xad, 0xfb, 0xca, 0xde}))
})
It("sets the negotiated value for maximum streams in the SHLO", func() {
val := 50
Expect(val).To(BeNumerically("<", protocol.MaxStreamsPerConnection))
err := pn.SetFromMap(map[Tag][]byte{TagMSPC: []byte{byte(val), 0, 0, 0}})
Expect(err).ToNot(HaveOccurred())
entryMap, err := pn.GetHelloMap()
Expect(err).ToNot(HaveOccurred())
Expect(entryMap[TagMSPC]).To(Equal([]byte{byte(val), 0, 0, 0}))
})
It("always sends its own value for the maximum incoming dynamic streams in the SHLO", func() {
err := pn.SetFromMap(map[Tag][]byte{TagMIDS: []byte{5, 0, 0, 0}})
Expect(err).ToNot(HaveOccurred())
@@ -98,8 +87,6 @@ var _ = Describe("Params Negotiator (for gQUIC)", func() {
Expect(err).ToNot(HaveOccurred())
Expect(entryMap).To(HaveKey(TagICSL))
Expect(binary.LittleEndian.Uint32(entryMap[TagICSL])).To(BeEquivalentTo(idleTimeout / time.Second))
Expect(entryMap).To(HaveKey(TagMSPC))
Expect(binary.LittleEndian.Uint32(entryMap[TagMSPC])).To(BeEquivalentTo(protocol.MaxStreamsPerConnection))
Expect(entryMap).To(HaveKey(TagMIDS))
Expect(binary.LittleEndian.Uint32(entryMap[TagMIDS])).To(BeEquivalentTo(protocol.MaxIncomingDynamicStreamsPerConnection))
Expect(entryMap).To(HaveKey(TagSFCW))
@@ -223,12 +210,6 @@ var _ = Describe("Params Negotiator (for gQUIC)", func() {
})
Context("max streams per connection", 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 := pn.SetFromMap(values)
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 := pn.SetFromMap(values)
@@ -240,28 +221,18 @@ var _ = Describe("Params Negotiator (for gQUIC)", func() {
// this test only works if the value given here is smaller than protocol.MaxStreamsPerConnection
err := pn.SetFromMap(map[Tag][]byte{
TagMIDS: {2, 0, 0, 0},
TagMSPC: {1, 0, 0, 0},
})
Expect(err).ToNot(HaveOccurred())
Expect(pn.GetMaxOutgoingStreams()).To(Equal(uint32(2)))
})
It("uses the the MSPC value, if no MIDS is given", func() {
err := pn.SetFromMap(map[Tag][]byte{TagMIDS: {3, 0, 0, 0}})
err := pn.SetFromMap(map[Tag][]byte{
TagMIDS: {3, 0, 0, 0},
})
Expect(err).ToNot(HaveOccurred())
Expect(pn.GetMaxOutgoingStreams()).To(Equal(uint32(3)))
})
})
Context("incoming connections", func() {
It("always uses the constant value, no matter what the client sent", func() {
err := pn.SetFromMap(map[Tag][]byte{
TagMSPC: {3, 0, 0, 0},
TagMIDS: {3, 0, 0, 0},
})
Expect(err).ToNot(HaveOccurred())
Expect(pn.GetMaxIncomingStreams()).To(BeNumerically(">", protocol.MaxStreamsPerConnection))
})
})
})
})

View File

@@ -95,18 +95,6 @@ func (mr *MockParamsNegotiatorMockRecorder) GetMaxOutgoingStreams() *gomock.Call
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMaxOutgoingStreams", reflect.TypeOf((*MockParamsNegotiator)(nil).GetMaxOutgoingStreams))
}
// GetMaxIncomingStreams mocks base method
func (m *MockParamsNegotiator) GetMaxIncomingStreams() uint32 {
ret := m.ctrl.Call(m, "GetMaxIncomingStreams")
ret0, _ := ret[0].(uint32)
return ret0
}
// GetMaxIncomingStreams indicates an expected call of GetMaxIncomingStreams
func (mr *MockParamsNegotiatorMockRecorder) GetMaxIncomingStreams() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMaxIncomingStreams", reflect.TypeOf((*MockParamsNegotiator)(nil).GetMaxIncomingStreams))
}
// GetRemoteIdleTimeout mocks base method
func (m *MockParamsNegotiator) GetRemoteIdleTimeout() time.Duration {
ret := m.ctrl.Call(m, "GetRemoteIdleTimeout")