github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/internal/ackhandler/received_packet_history.go (about) 1 package ackhandler 2 3 import ( 4 "sync" 5 6 "github.com/apernet/quic-go/internal/protocol" 7 list "github.com/apernet/quic-go/internal/utils/linkedlist" 8 "github.com/apernet/quic-go/internal/wire" 9 ) 10 11 // interval is an interval from one PacketNumber to the other 12 type interval struct { 13 Start protocol.PacketNumber 14 End protocol.PacketNumber 15 } 16 17 var intervalElementPool sync.Pool 18 19 func init() { 20 intervalElementPool = *list.NewPool[interval]() 21 } 22 23 // The receivedPacketHistory stores if a packet number has already been received. 24 // It generates ACK ranges which can be used to assemble an ACK frame. 25 // It does not store packet contents. 26 type receivedPacketHistory struct { 27 ranges *list.List[interval] 28 29 deletedBelow protocol.PacketNumber 30 } 31 32 func newReceivedPacketHistory() *receivedPacketHistory { 33 return &receivedPacketHistory{ 34 ranges: list.NewWithPool[interval](&intervalElementPool), 35 } 36 } 37 38 // ReceivedPacket registers a packet with PacketNumber p and updates the ranges 39 func (h *receivedPacketHistory) ReceivedPacket(p protocol.PacketNumber) bool /* is a new packet (and not a duplicate / delayed packet) */ { 40 // ignore delayed packets, if we already deleted the range 41 if p < h.deletedBelow { 42 return false 43 } 44 isNew := h.addToRanges(p) 45 h.maybeDeleteOldRanges() 46 return isNew 47 } 48 49 func (h *receivedPacketHistory) addToRanges(p protocol.PacketNumber) bool /* is a new packet (and not a duplicate / delayed packet) */ { 50 if h.ranges.Len() == 0 { 51 h.ranges.PushBack(interval{Start: p, End: p}) 52 return true 53 } 54 55 for el := h.ranges.Back(); el != nil; el = el.Prev() { 56 // p already included in an existing range. Nothing to do here 57 if p >= el.Value.Start && p <= el.Value.End { 58 return false 59 } 60 61 if el.Value.End == p-1 { // extend a range at the end 62 el.Value.End = p 63 return true 64 } 65 if el.Value.Start == p+1 { // extend a range at the beginning 66 el.Value.Start = p 67 68 prev := el.Prev() 69 if prev != nil && prev.Value.End+1 == el.Value.Start { // merge two ranges 70 prev.Value.End = el.Value.End 71 h.ranges.Remove(el) 72 } 73 return true 74 } 75 76 // create a new range at the end 77 if p > el.Value.End { 78 h.ranges.InsertAfter(interval{Start: p, End: p}, el) 79 return true 80 } 81 } 82 83 // create a new range at the beginning 84 h.ranges.InsertBefore(interval{Start: p, End: p}, h.ranges.Front()) 85 return true 86 } 87 88 // Delete old ranges, if we're tracking more than 500 of them. 89 // This is a DoS defense against a peer that sends us too many gaps. 90 func (h *receivedPacketHistory) maybeDeleteOldRanges() { 91 for h.ranges.Len() > protocol.MaxNumAckRanges { 92 h.ranges.Remove(h.ranges.Front()) 93 } 94 } 95 96 // DeleteBelow deletes all entries below (but not including) p 97 func (h *receivedPacketHistory) DeleteBelow(p protocol.PacketNumber) { 98 if p < h.deletedBelow { 99 return 100 } 101 h.deletedBelow = p 102 103 nextEl := h.ranges.Front() 104 for el := h.ranges.Front(); nextEl != nil; el = nextEl { 105 nextEl = el.Next() 106 107 if el.Value.End < p { // delete a whole range 108 h.ranges.Remove(el) 109 } else if p > el.Value.Start && p <= el.Value.End { 110 el.Value.Start = p 111 return 112 } else { // no ranges affected. Nothing to do 113 return 114 } 115 } 116 } 117 118 // AppendAckRanges appends to a slice of all AckRanges that can be used in an AckFrame 119 func (h *receivedPacketHistory) AppendAckRanges(ackRanges []wire.AckRange) []wire.AckRange { 120 if h.ranges.Len() > 0 { 121 for el := h.ranges.Back(); el != nil; el = el.Prev() { 122 ackRanges = append(ackRanges, wire.AckRange{Smallest: el.Value.Start, Largest: el.Value.End}) 123 } 124 } 125 return ackRanges 126 } 127 128 func (h *receivedPacketHistory) GetHighestAckRange() wire.AckRange { 129 ackRange := wire.AckRange{} 130 if h.ranges.Len() > 0 { 131 r := h.ranges.Back().Value 132 ackRange.Smallest = r.Start 133 ackRange.Largest = r.End 134 } 135 return ackRange 136 } 137 138 func (h *receivedPacketHistory) IsPotentiallyDuplicate(p protocol.PacketNumber) bool { 139 if p < h.deletedBelow { 140 return true 141 } 142 for el := h.ranges.Back(); el != nil; el = el.Prev() { 143 if p > el.Value.End { 144 return false 145 } 146 if p <= el.Value.End && p >= el.Value.Start { 147 return true 148 } 149 } 150 return false 151 }