diff --git a/conn_id_manager.go b/conn_id_manager.go index 9db3733e..7a373493 100644 --- a/conn_id_manager.go +++ b/conn_id_manager.go @@ -9,9 +9,27 @@ import ( type connIDManager struct { queue utils.NewConnectionIDList + + queueControlFrame func(wire.Frame) +} + +func newConnIDManager(queueControlFrame func(wire.Frame)) *connIDManager { + return &connIDManager{queueControlFrame: queueControlFrame} } func (h *connIDManager) Add(f *wire.NewConnectionIDFrame) error { + var next *utils.NewConnectionIDElement + for el := h.queue.Front(); el != nil; el = next { + if el.Value.SequenceNumber >= f.RetirePriorTo { + break + } + next = el.Next() + h.queueControlFrame(&wire.RetireConnectionIDFrame{ + SequenceNumber: el.Value.SequenceNumber, + }) + h.queue.Remove(el) + } + // insert a new element at the end if h.queue.Len() == 0 || h.queue.Back().Value.SequenceNumber < f.SequenceNumber { h.queue.PushBack(utils.NewConnectionID{ diff --git a/conn_id_manager_test.go b/conn_id_manager_test.go index 7c531ea5..6b707e5e 100644 --- a/conn_id_manager_test.go +++ b/conn_id_manager_test.go @@ -8,10 +8,16 @@ import ( ) var _ = Describe("Connection ID Manager", func() { - var m *connIDManager + var ( + m *connIDManager + frameQueue []wire.Frame + ) BeforeEach(func() { - m = &connIDManager{} + frameQueue = nil + m = newConnIDManager(func(f wire.Frame) { + frameQueue = append(frameQueue, f) + }) }) get := func() (protocol.ConnectionID, *[16]byte) { @@ -89,4 +95,26 @@ var _ = Describe("Connection ID Manager", func() { StatelessResetToken: [16]byte{0xe, 0xd, 0xc, 0xb, 0xa, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, })).To(MatchError("received conflicting stateless reset tokens for sequence number 42")) }) + + It("retires connection IDs", func() { + Expect(m.Add(&wire.NewConnectionIDFrame{ + SequenceNumber: 10, + ConnectionID: protocol.ConnectionID{1, 2, 3, 4}, + })).To(Succeed()) + Expect(m.Add(&wire.NewConnectionIDFrame{ + SequenceNumber: 13, + ConnectionID: protocol.ConnectionID{2, 3, 4, 5}, + })).To(Succeed()) + Expect(frameQueue).To(BeEmpty()) + Expect(m.Add(&wire.NewConnectionIDFrame{ + RetirePriorTo: 14, + SequenceNumber: 17, + ConnectionID: protocol.ConnectionID{3, 4, 5, 6}, + })).To(Succeed()) + Expect(frameQueue).To(HaveLen(2)) + Expect(frameQueue[0].(*wire.RetireConnectionIDFrame).SequenceNumber).To(BeEquivalentTo(10)) + Expect(frameQueue[1].(*wire.RetireConnectionIDFrame).SequenceNumber).To(BeEquivalentTo(13)) + c, _ := get() + Expect(c).To(Equal(protocol.ConnectionID{3, 4, 5, 6})) + }) })