diff --git a/conn_id_manager.go b/conn_id_manager.go index 7a373493d..1bed99282 100644 --- a/conn_id_manager.go +++ b/conn_id_manager.go @@ -3,6 +3,7 @@ package quic import ( "fmt" + "github.com/lucas-clemente/quic-go/internal/protocol" "github.com/lucas-clemente/quic-go/internal/utils" "github.com/lucas-clemente/quic-go/internal/wire" ) @@ -18,6 +19,20 @@ func newConnIDManager(queueControlFrame func(wire.Frame)) *connIDManager { } func (h *connIDManager) Add(f *wire.NewConnectionIDFrame) error { + if err := h.add(f); err != nil { + return err + } + if h.queue.Len() > protocol.MaxActiveConnectionIDs { + // delete the first connection ID in the queue + val := h.queue.Remove(h.queue.Front()) + h.queueControlFrame(&wire.RetireConnectionIDFrame{ + SequenceNumber: val.SequenceNumber, + }) + } + return nil +} + +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 { diff --git a/conn_id_manager_test.go b/conn_id_manager_test.go index 6b707e5ef..6419ef1ab 100644 --- a/conn_id_manager_test.go +++ b/conn_id_manager_test.go @@ -117,4 +117,20 @@ var _ = Describe("Connection ID Manager", func() { c, _ := get() Expect(c).To(Equal(protocol.ConnectionID{3, 4, 5, 6})) }) + + It("retires old connection IDs when the peer sends too many new ones", func() { + for i := uint8(0); i < protocol.MaxActiveConnectionIDs; i++ { + Expect(m.Add(&wire.NewConnectionIDFrame{ + SequenceNumber: uint64(i), + ConnectionID: protocol.ConnectionID{i, i, i, i}, + })).To(Succeed()) + } + Expect(frameQueue).To(BeEmpty()) + Expect(m.Add(&wire.NewConnectionIDFrame{ + SequenceNumber: protocol.MaxActiveConnectionIDs, + ConnectionID: protocol.ConnectionID{1, 2, 3, 4}, + })).To(Succeed()) + Expect(frameQueue).To(HaveLen(1)) + Expect(frameQueue[0].(*wire.RetireConnectionIDFrame).SequenceNumber).To(BeEquivalentTo(0)) + }) })