github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/internal/ackhandler/received_packet_history.go (about)

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