From 011642e4710cb8d87a901562e241985df454398c Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Sat, 26 Oct 2019 17:50:40 +0700 Subject: [PATCH] update the connection ID after sending 10000 packets --- conn_id_manager.go | 22 ++++++++++++++++ conn_id_manager_test.go | 50 +++++++++++++++++++++++++++++++++++++ internal/protocol/params.go | 4 +++ session.go | 3 ++- 4 files changed, 78 insertions(+), 1 deletion(-) diff --git a/conn_id_manager.go b/conn_id_manager.go index 126ec5718..d2e1ca2d1 100644 --- a/conn_id_manager.go +++ b/conn_id_manager.go @@ -15,6 +15,8 @@ type connIDManager struct { activeConnectionID protocol.ConnectionID activeStatelessResetToken *[16]byte + packetsSinceLastChange uint64 + addStatelessResetToken func([16]byte) retireStatelessResetToken func([16]byte) queueControlFrame func(wire.Frame) @@ -108,6 +110,7 @@ func (h *connIDManager) updateConnectionID() { h.activeSequenceNumber = front.SequenceNumber h.activeConnectionID = front.ConnectionID h.activeStatelessResetToken = front.StatelessResetToken + h.packetsSinceLastChange = 0 h.addStatelessResetToken(*h.activeStatelessResetToken) } @@ -129,6 +132,25 @@ func (h *connIDManager) SetStatelessResetToken(token [16]byte) { h.addStatelessResetToken(token) } +func (h *connIDManager) SentPacket() { + h.packetsSinceLastChange++ +} + +func (h *connIDManager) shouldUpdateConnID() bool { + // iniate the first change as early as possible + if h.queue.Len() > 0 && h.activeSequenceNumber == 0 { + return true + } + // For later changes, only change if + // 1. The queue of connection IDs is filled more than 50%. + // 2. We sent at least PacketsPerConnectionID packets + return 2*h.queue.Len() >= protocol.MaxActiveConnectionIDs && + h.packetsSinceLastChange >= protocol.PacketsPerConnectionID +} + func (h *connIDManager) Get() protocol.ConnectionID { + if h.shouldUpdateConnID() { + h.updateConnectionID() + } return h.activeConnectionID } diff --git a/conn_id_manager_test.go b/conn_id_manager_test.go index 3819cc6b4..2f293ba67 100644 --- a/conn_id_manager_test.go +++ b/conn_id_manager_test.go @@ -159,4 +159,54 @@ var _ = Describe("Connection ID Manager", func() { Expect(retiredTokens).To(HaveLen(1)) Expect(retiredTokens[0]).To(Equal([16]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})) }) + + It("initiates the first connection ID update as soon as possible", func() { + Expect(m.Get()).To(Equal(initialConnID)) + Expect(m.Add(&wire.NewConnectionIDFrame{ + SequenceNumber: 1, + ConnectionID: protocol.ConnectionID{1, 2, 3, 4}, + StatelessResetToken: [16]byte{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, + })).To(Succeed()) + Expect(m.Get()).To(Equal(protocol.ConnectionID{1, 2, 3, 4})) + + }) + + It("initiates subsequent updates when enough packets are sent", func() { + for i := uint8(1); i <= protocol.MaxActiveConnectionIDs; i++ { + Expect(m.Add(&wire.NewConnectionIDFrame{ + SequenceNumber: uint64(i), + ConnectionID: protocol.ConnectionID{i, i, i, i}, + StatelessResetToken: [16]byte{i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i}, + })).To(Succeed()) + } + Expect(m.Get()).To(Equal(protocol.ConnectionID{1, 1, 1, 1})) + for i := 0; i < protocol.PacketsPerConnectionID; i++ { + m.SentPacket() + } + Expect(m.Get()).To(Equal(protocol.ConnectionID{2, 2, 2, 2})) + Expect(retiredTokens).To(HaveLen(1)) + Expect(retiredTokens[0]).To(Equal([16]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})) + }) + + 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{ + SequenceNumber: uint64(i), + ConnectionID: protocol.ConnectionID{i, i, i, i}, + StatelessResetToken: [16]byte{i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i}, + })).To(Succeed()) + } + Expect(m.Get()).To(Equal(protocol.ConnectionID{1, 1, 1, 1})) + for i := 0; i < 2*protocol.PacketsPerConnectionID; i++ { + m.SentPacket() + } + Expect(m.Get()).To(Equal(protocol.ConnectionID{1, 1, 1, 1})) + Expect(m.Add(&wire.NewConnectionIDFrame{ + SequenceNumber: 1337, + ConnectionID: protocol.ConnectionID{1, 3, 3, 7}, + })).To(Succeed()) + Expect(m.Get()).To(Equal(protocol.ConnectionID{2, 2, 2, 2})) + Expect(retiredTokens).To(HaveLen(1)) + Expect(retiredTokens[0]).To(Equal([16]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})) + }) }) diff --git a/internal/protocol/params.go b/internal/protocol/params.go index bd6a2c7ce..f94ef690b 100644 --- a/internal/protocol/params.go +++ b/internal/protocol/params.go @@ -136,6 +136,10 @@ const DefaultConnectionIDLength = 4 // MaxActiveConnectionIDs is the number of connection IDs that we're storing. const MaxActiveConnectionIDs = 4 +// PacketsPerConnectionID is the number of packets we send using one connection ID. +// If the peer provices us with enough new connection IDs, we switch to a new connection ID. +const PacketsPerConnectionID = 10000 + // AckDelayExponent is the ack delay exponent used when sending ACKs. const AckDelayExponent = 3 diff --git a/session.go b/session.go index 3c3239316..780f5ad61 100644 --- a/session.go +++ b/session.go @@ -1126,7 +1126,7 @@ func (s *session) maybeSendAckOnlyPacket() error { return nil } s.sentPacketHandler.SentPacket(packet.ToAckHandlerPacket(s.retransmissionQueue)) - s.sendQueue.Send(packet) + s.sendPackedPacket(packet) return nil } @@ -1182,6 +1182,7 @@ func (s *session) sendPackedPacket(packet *packedPacket) { }) } s.logPacket(packet) + s.connIDManager.SentPacket() s.sendQueue.Send(packet) }