delete 0-RTT queues if no Initial is received within 100ms

This commit is contained in:
Marten Seemann 2020-01-03 16:32:19 +07:00
parent 2b7133a6e2
commit ba095dd3ff
3 changed files with 40 additions and 13 deletions

View file

@ -159,6 +159,9 @@ const MaxAckDelayInclGranularity = MaxAckDelay + TimerGranularity
// KeyUpdateInterval is the maximum number of packets we send or receive before initiating a key udpate.
const KeyUpdateInterval = 100 * 1000
// Max0RTTQueueingDuration is the maximum time that we store 0-RTT packets in order to wait for the corresponding Initial to be received.
const Max0RTTQueueingDuration = 100 * time.Millisecond
// Max0RTTQueues is the maximum number of connections that we buffer 0-RTT packets for.
const Max0RTTQueues = 32

View file

@ -2,17 +2,23 @@ package quic
import (
"sync"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
)
type zeroRTTQueueEntry struct {
timer *time.Timer
packets []*receivedPacket
}
type zeroRTTQueue struct {
mutex sync.Mutex
queue map[string][]*receivedPacket
queue map[string]*zeroRTTQueueEntry
}
func newZeroRTTQueue() *zeroRTTQueue {
return &zeroRTTQueue{queue: make(map[string][]*receivedPacket)}
return &zeroRTTQueue{queue: make(map[string]*zeroRTTQueueEntry)}
}
func (h *zeroRTTQueue) Enqueue(connID protocol.ConnectionID, p *receivedPacket) {
@ -20,27 +26,36 @@ func (h *zeroRTTQueue) Enqueue(connID protocol.ConnectionID, p *receivedPacket)
defer h.mutex.Unlock()
cid := string(connID)
if _, ok := h.queue[cid]; !ok && len(h.queue) >= protocol.Max0RTTQueues {
if _, ok := h.queue[cid]; !ok {
if len(h.queue) >= protocol.Max0RTTQueues {
return
}
h.queue[cid] = &zeroRTTQueueEntry{timer: time.AfterFunc(protocol.Max0RTTQueueingDuration, func() {
h.mutex.Lock()
delete(h.queue, cid)
h.mutex.Unlock()
})}
}
entry := h.queue[cid]
if len(entry.packets) >= protocol.Max0RTTQueueLen {
return
}
if len(h.queue[cid]) >= protocol.Max0RTTQueueLen {
return
}
h.queue[cid] = append(h.queue[cid], p)
entry.packets = append(entry.packets, p)
}
func (h *zeroRTTQueue) Dequeue(connID protocol.ConnectionID) *receivedPacket {
h.mutex.Lock()
defer h.mutex.Unlock()
cid := string(connID)
if _, ok := h.queue[cid]; !ok {
entry, ok := h.queue[string(connID)]
if !ok {
return nil
}
p := h.queue[cid][0]
h.queue[cid] = h.queue[cid][1:]
if len(h.queue[cid]) == 0 {
delete(h.queue, cid)
p := entry.packets[0]
entry.packets = entry.packets[1:]
if len(entry.packets) == 0 {
entry.timer.Stop()
delete(h.queue, string(connID))
}
return p
}

View file

@ -2,6 +2,7 @@ package quic
import (
"encoding/binary"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
@ -85,4 +86,12 @@ var _ = Describe("0-RTT queue", func() {
// The queue should now be empty.
Expect(q.Dequeue(connID)).To(BeNil())
})
It("deletes packets if they aren't dequeued after a short while", func() {
connID := protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}
p := &receivedPacket{data: []byte("foobar")}
q.Enqueue(connID, p)
time.Sleep(protocol.Max0RTTQueueingDuration * 3 / 2)
Expect(q.Dequeue(connID)).To(BeNil())
})
})