retire delayed conn IDs arriving after a higher conn ID was retired

This commit is contained in:
Marten Seemann 2019-11-24 10:12:02 +07:00
parent a53569839c
commit f1fd07df59
2 changed files with 36 additions and 5 deletions

View file

@ -15,7 +15,7 @@ type connIDManager struct {
queue utils.NewConnectionIDList
activeSequenceNumber uint64
retiredPriorTo uint64
highestRetired uint64
activeConnectionID protocol.ConnectionID
activeStatelessResetToken *[16]byte
@ -65,7 +65,7 @@ func (h *connIDManager) Add(f *wire.NewConnectionIDFrame) error {
func (h *connIDManager) add(f *wire.NewConnectionIDFrame) error {
// If the NEW_CONNECTION_ID frame is reordered, such that its sequenece number
// was already retired, send the RETIRE_CONNECTION_ID frame immediately.
if f.SequenceNumber < h.retiredPriorTo {
if f.SequenceNumber < h.highestRetired {
h.queueControlFrame(&wire.RetireConnectionIDFrame{
SequenceNumber: f.SequenceNumber,
})
@ -74,7 +74,7 @@ func (h *connIDManager) add(f *wire.NewConnectionIDFrame) error {
// Retire elements in the queue.
// Doesn't retire the active connection ID.
if f.RetirePriorTo > h.retiredPriorTo {
if f.RetirePriorTo > h.highestRetired {
var next *utils.NewConnectionIDElement
for el := h.queue.Front(); el != nil; el = next {
if el.Value.SequenceNumber >= f.RetirePriorTo {
@ -86,7 +86,7 @@ func (h *connIDManager) add(f *wire.NewConnectionIDFrame) error {
})
h.queue.Remove(el)
}
h.retiredPriorTo = f.RetirePriorTo
h.highestRetired = f.RetirePriorTo
}
if f.SequenceNumber == h.activeSequenceNumber {
@ -135,9 +135,11 @@ func (h *connIDManager) updateConnectionID() {
h.queueControlFrame(&wire.RetireConnectionIDFrame{
SequenceNumber: h.activeSequenceNumber,
})
h.highestRetired = utils.MaxUint64(h.highestRetired, h.activeSequenceNumber)
if h.activeStatelessResetToken != nil {
h.retireStatelessResetToken(*h.activeStatelessResetToken)
}
front := h.queue.Remove(h.queue.Front())
h.activeSequenceNumber = front.SequenceNumber
h.activeConnectionID = front.ConnectionID

View file

@ -15,7 +15,7 @@ var _ = Describe("Connection ID Manager", func() {
retiredTokens [][16]byte
removedTokens [][16]byte
)
initialConnID := protocol.ConnectionID{1, 1, 1, 1}
initialConnID := protocol.ConnectionID{0, 0, 0, 0}
BeforeEach(func() {
frameQueue = nil
@ -243,6 +243,35 @@ var _ = Describe("Connection ID Manager", func() {
Expect(counter).To(BeNumerically("~", 50, 10))
})
It("retires delayed connection IDs that arrive after a higher connection ID was already retired", func() {
for s := uint8(10); s <= 10+protocol.MaxActiveConnectionIDs/2; s++ {
Expect(m.Add(&wire.NewConnectionIDFrame{
SequenceNumber: uint64(s),
ConnectionID: protocol.ConnectionID{s, s, s, s},
StatelessResetToken: [16]byte{s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s},
})).To(Succeed())
}
Expect(m.Get()).To(Equal(protocol.ConnectionID{10, 10, 10, 10}))
for {
m.SentPacket()
if m.Get().Equal(protocol.ConnectionID{11, 11, 11, 11}) {
break
}
}
// The active conn ID is now {11, 11, 11, 11}
Expect(m.queue.Front().Value.ConnectionID).To(Equal(protocol.ConnectionID{12, 12, 12, 12}))
// Add a delayed connection ID. It should just be ignored now.
frameQueue = nil
Expect(m.Add(&wire.NewConnectionIDFrame{
SequenceNumber: uint64(5),
ConnectionID: protocol.ConnectionID{5, 5, 5, 5},
StatelessResetToken: [16]byte{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
})).To(Succeed())
Expect(m.queue.Front().Value.ConnectionID).To(Equal(protocol.ConnectionID{12, 12, 12, 12}))
Expect(frameQueue).To(HaveLen(1))
Expect(frameQueue[0].(*wire.RetireConnectionIDFrame).SequenceNumber).To(BeEquivalentTo(5))
})
It("only initiates subsequent updates when enough if enough connection IDs are queued", func() {
for i := uint8(1); i <= protocol.MaxActiveConnectionIDs/2; i++ {
Expect(m.Add(&wire.NewConnectionIDFrame{