forked from quic-go/quic-go
@@ -18,6 +18,7 @@ type ConnectionParametersManager struct {
|
||||
params map[Tag][]byte
|
||||
mutex sync.RWMutex
|
||||
|
||||
idleConnectionStateLifetime time.Duration
|
||||
sendStreamFlowControlWindow protocol.ByteCount
|
||||
sendConnectionFlowControlWindow protocol.ByteCount
|
||||
receiveStreamFlowControlWindow protocol.ByteCount
|
||||
@@ -31,9 +32,9 @@ var ErrTagNotInConnectionParameterMap = errors.New("Tag not found in Connections
|
||||
func NewConnectionParamatersManager() *ConnectionParametersManager {
|
||||
return &ConnectionParametersManager{
|
||||
params: map[Tag][]byte{
|
||||
TagICSL: {0x1e, 0x00, 0x00, 0x00}, // idle connection state lifetime = 30s
|
||||
TagMSPC: {0x64, 0x00, 0x00, 0x00}, // Max streams per connection = 100
|
||||
},
|
||||
idleConnectionStateLifetime: protocol.InitialIdleConnectionStateLifetime,
|
||||
sendStreamFlowControlWindow: protocol.InitialStreamFlowControlWindow, // can only be changed by the client
|
||||
sendConnectionFlowControlWindow: protocol.InitialConnectionFlowControlWindow, // can only be changed by the client
|
||||
receiveStreamFlowControlWindow: protocol.ReceiveStreamFlowControlWindow,
|
||||
@@ -48,8 +49,14 @@ func (h *ConnectionParametersManager) SetFromMap(params map[Tag][]byte) error {
|
||||
|
||||
for key, value := range params {
|
||||
switch key {
|
||||
case TagICSL, TagMSPC, TagTCID:
|
||||
case TagMSPC, TagTCID:
|
||||
h.params[key] = value
|
||||
case TagICSL:
|
||||
clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.idleConnectionStateLifetime = h.negotiateIdleConnectionStateLifetime(time.Duration(clientValue) * time.Second)
|
||||
case TagSFCW:
|
||||
sendStreamFlowControlWindow, err := utils.ReadUint32(bytes.NewBuffer(value))
|
||||
if err != nil {
|
||||
@@ -68,6 +75,11 @@ func (h *ConnectionParametersManager) SetFromMap(params map[Tag][]byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *ConnectionParametersManager) negotiateIdleConnectionStateLifetime(clientValue time.Duration) time.Duration {
|
||||
// TODO: what happens if the clients sets 0 seconds?
|
||||
return utils.MinDuration(clientValue, protocol.MaxIdleConnectionStateLifetime)
|
||||
}
|
||||
|
||||
// getRawValue gets the byte-slice for a tag
|
||||
func (h *ConnectionParametersManager) getRawValue(tag Tag) ([]byte, error) {
|
||||
h.mutex.RLock()
|
||||
@@ -83,12 +95,15 @@ func (h *ConnectionParametersManager) getRawValue(tag Tag) ([]byte, error) {
|
||||
// GetSHLOMap gets all values (except crypto values) needed for the SHLO
|
||||
func (h *ConnectionParametersManager) GetSHLOMap() map[Tag][]byte {
|
||||
sfcw := bytes.NewBuffer([]byte{})
|
||||
cfcw := bytes.NewBuffer([]byte{})
|
||||
utils.WriteUint32(sfcw, uint32(h.GetReceiveStreamFlowControlWindow()))
|
||||
cfcw := bytes.NewBuffer([]byte{})
|
||||
utils.WriteUint32(cfcw, uint32(h.GetReceiveConnectionFlowControlWindow()))
|
||||
icsl := bytes.NewBuffer([]byte{})
|
||||
utils.Debugf("ICSL: %#v\n", h.GetIdleConnectionStateLifetime())
|
||||
utils.WriteUint32(icsl, uint32(h.GetIdleConnectionStateLifetime()/time.Second))
|
||||
|
||||
return map[Tag][]byte{
|
||||
TagICSL: []byte{0x1e, 0x00, 0x00, 0x00}, //30
|
||||
TagICSL: icsl.Bytes(),
|
||||
TagMSPC: []byte{0x64, 0x00, 0x00, 0x00}, //100
|
||||
TagCFCW: cfcw.Bytes(),
|
||||
TagSFCW: sfcw.Bytes(),
|
||||
@@ -129,14 +144,10 @@ func (h *ConnectionParametersManager) GetReceiveConnectionFlowControlWindow() pr
|
||||
|
||||
// GetIdleConnectionStateLifetime gets the idle timeout
|
||||
func (h *ConnectionParametersManager) GetIdleConnectionStateLifetime() time.Duration {
|
||||
rawValue, err := h.getRawValue(TagICSL)
|
||||
if err != nil {
|
||||
panic("ConnectionParameters: Could not find ICSL")
|
||||
}
|
||||
if len(rawValue) != 4 {
|
||||
panic("ConnectionParameters: ICSL has invalid value")
|
||||
}
|
||||
return time.Duration(binary.LittleEndian.Uint32(rawValue)) * time.Second
|
||||
h.mutex.RLock()
|
||||
defer h.mutex.RUnlock()
|
||||
|
||||
return h.idleConnectionStateLifetime
|
||||
}
|
||||
|
||||
// TruncateConnectionID determines if the client requests truncated ConnectionIDs
|
||||
|
||||
@@ -15,16 +15,16 @@ var _ = Describe("ConnectionsParameterManager", func() {
|
||||
})
|
||||
|
||||
It("stores and retrieves a value", func() {
|
||||
icsl := []byte{0x13, 0x37}
|
||||
mspc := []byte{0x13, 0x37}
|
||||
values := map[Tag][]byte{
|
||||
TagICSL: icsl,
|
||||
TagMSPC: mspc,
|
||||
}
|
||||
|
||||
cpm.SetFromMap(values)
|
||||
|
||||
val, err := cpm.getRawValue(TagICSL)
|
||||
val, err := cpm.getRawValue(TagMSPC)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).To(Equal(icsl))
|
||||
Expect(val).To(Equal(mspc))
|
||||
})
|
||||
|
||||
It("returns an error for a tag that is not set", func() {
|
||||
@@ -53,6 +53,13 @@ var _ = Describe("ConnectionsParameterManager", func() {
|
||||
Expect(entryMap).To(HaveKey(TagCFCW))
|
||||
Expect(entryMap[TagCFCW]).To(Equal([]byte{0xAD, 0xFB, 0xCA, 0xDE}))
|
||||
})
|
||||
|
||||
It("returns connection-level flow control windows in SHLO", func() {
|
||||
cpm.idleConnectionStateLifetime = 0xDECAFBAD * time.Second
|
||||
entryMap := cpm.GetSHLOMap()
|
||||
Expect(entryMap).To(HaveKey(TagICSL))
|
||||
Expect(entryMap[TagICSL]).To(Equal([]byte{0xAD, 0xFB, 0xCA, 0xDE}))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Truncated connection IDs", func() {
|
||||
@@ -123,14 +130,33 @@ var _ = Describe("ConnectionsParameterManager", func() {
|
||||
})
|
||||
})
|
||||
|
||||
It("gets idle connection state lifetime", func() {
|
||||
cpm.params[TagICSL] = []byte{0xad, 0xfb, 0xca, 0xde}
|
||||
val := cpm.GetIdleConnectionStateLifetime()
|
||||
Expect(val).To(Equal(0xdecafbad * time.Second))
|
||||
})
|
||||
Context("idle connection state lifetime", func() {
|
||||
It("has initial idle conneciton state lifetime", func() {
|
||||
Expect(cpm.GetIdleConnectionStateLifetime()).To(Equal(protocol.InitialIdleConnectionStateLifetime))
|
||||
})
|
||||
|
||||
It("has initial idle conneciton state lifetime", func() {
|
||||
val := cpm.GetIdleConnectionStateLifetime()
|
||||
Expect(val).To(Equal(30 * time.Second))
|
||||
It("negotiates correctly when the client wants a longer lifetime", func() {
|
||||
Expect(cpm.negotiateIdleConnectionStateLifetime(protocol.MaxIdleConnectionStateLifetime + 10*time.Second)).To(Equal(protocol.MaxIdleConnectionStateLifetime))
|
||||
})
|
||||
|
||||
It("negotiates correctly when the client wants a shorter lifetime", func() {
|
||||
Expect(cpm.negotiateIdleConnectionStateLifetime(protocol.MaxIdleConnectionStateLifetime - 1*time.Second)).To(Equal(protocol.MaxIdleConnectionStateLifetime - 1*time.Second))
|
||||
})
|
||||
|
||||
It("sets the negotiated lifetime", func() {
|
||||
// this test only works if the value given here is smaller than protocol.MaxIdleConnectionStateLifetime
|
||||
values := map[Tag][]byte{
|
||||
TagICSL: []byte{10, 0, 0, 0},
|
||||
}
|
||||
err := cpm.SetFromMap(values)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(cpm.GetIdleConnectionStateLifetime()).To(Equal(10 * time.Second))
|
||||
})
|
||||
|
||||
It("gets idle connection state lifetime", func() {
|
||||
value := 0xDECAFBAD * time.Second
|
||||
cpm.idleConnectionStateLifetime = value
|
||||
Expect(cpm.GetIdleConnectionStateLifetime()).To(Equal(value))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user