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

     1  package ackhandler
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/protocol"
     7  	"github.com/danielpfeifer02/quic-go-prio-packs/packet_setting"
     8  )
     9  
    10  type sentPacketHistory struct {
    11  	packets []*packet
    12  
    13  	numOutstanding int
    14  
    15  	highestPacketNumber protocol.PacketNumber
    16  }
    17  
    18  func newSentPacketHistory() *sentPacketHistory {
    19  	return &sentPacketHistory{
    20  		packets:             make([]*packet, 0, 32),
    21  		highestPacketNumber: protocol.InvalidPacketNumber,
    22  	}
    23  }
    24  
    25  func (h *sentPacketHistory) checkSequentialPacketNumberUse(pn protocol.PacketNumber) {
    26  
    27  	// PACKET_NUMBER_TAG
    28  	if packet_setting.ALLOW_SETTING_PN {
    29  		return
    30  	}
    31  
    32  	if h.highestPacketNumber != protocol.InvalidPacketNumber {
    33  		if pn != h.highestPacketNumber+1 {
    34  			panic("non-sequential packet number use")
    35  		}
    36  	}
    37  }
    38  
    39  func (h *sentPacketHistory) SkippedPacket(pn protocol.PacketNumber) {
    40  	h.checkSequentialPacketNumberUse(pn)
    41  	h.highestPacketNumber = pn
    42  	h.packets = append(h.packets, &packet{
    43  		PacketNumber:  pn,
    44  		skippedPacket: true,
    45  	})
    46  }
    47  
    48  func (h *sentPacketHistory) SentNonAckElicitingPacket(pn protocol.PacketNumber) {
    49  	h.checkSequentialPacketNumberUse(pn)
    50  	h.highestPacketNumber = pn
    51  	if len(h.packets) > 0 {
    52  		h.packets = append(h.packets, nil)
    53  	}
    54  }
    55  
    56  func (h *sentPacketHistory) SentAckElicitingPacket(p *packet) {
    57  	h.checkSequentialPacketNumberUse(p.PacketNumber)
    58  	h.highestPacketNumber = p.PacketNumber
    59  	h.packets = append(h.packets, p)
    60  	if p.outstanding() {
    61  		h.numOutstanding++
    62  	}
    63  }
    64  
    65  // Iterate iterates through all packets.
    66  func (h *sentPacketHistory) Iterate(cb func(*packet) (cont bool, err error)) error {
    67  	for _, p := range h.packets {
    68  		if p == nil {
    69  			continue
    70  		}
    71  		cont, err := cb(p)
    72  		if err != nil {
    73  			return err
    74  		}
    75  		if !cont {
    76  			return nil
    77  		}
    78  	}
    79  	return nil
    80  }
    81  
    82  // FirstOutstanding returns the first outstanding packet.
    83  func (h *sentPacketHistory) FirstOutstanding() *packet {
    84  	if !h.HasOutstandingPackets() {
    85  		return nil
    86  	}
    87  	for _, p := range h.packets {
    88  		if p != nil && p.outstanding() {
    89  			return p
    90  		}
    91  	}
    92  	return nil
    93  }
    94  
    95  func (h *sentPacketHistory) Len() int {
    96  	return len(h.packets)
    97  }
    98  
    99  func (h *sentPacketHistory) Remove(pn protocol.PacketNumber) error {
   100  	idx, ok := h.getIndex(pn)
   101  	if !ok {
   102  		return fmt.Errorf("packet %d not found in sent packet history", pn)
   103  	}
   104  	p := h.packets[idx]
   105  	if p.outstanding() {
   106  		h.numOutstanding--
   107  		if h.numOutstanding < 0 {
   108  			panic("negative number of outstanding packets")
   109  		}
   110  	}
   111  	h.packets[idx] = nil
   112  	// clean up all skipped packets directly before this packet number
   113  	for idx > 0 {
   114  		idx--
   115  		p := h.packets[idx]
   116  		if p == nil || !p.skippedPacket {
   117  			break
   118  		}
   119  		h.packets[idx] = nil
   120  	}
   121  	if idx == 0 {
   122  		h.cleanupStart()
   123  	}
   124  	if len(h.packets) > 0 && h.packets[0] == nil {
   125  		panic("remove failed")
   126  	}
   127  	return nil
   128  }
   129  
   130  // getIndex gets the index of packet p in the packets slice.
   131  func (h *sentPacketHistory) getIndex(p protocol.PacketNumber) (int, bool) {
   132  	if len(h.packets) == 0 {
   133  		return 0, false
   134  	}
   135  	first := h.packets[0].PacketNumber
   136  	if p < first {
   137  		return 0, false
   138  	}
   139  	index := int(p - first)
   140  	if index > len(h.packets)-1 {
   141  		return 0, false
   142  	}
   143  	return index, true
   144  }
   145  
   146  func (h *sentPacketHistory) HasOutstandingPackets() bool {
   147  	return h.numOutstanding > 0
   148  }
   149  
   150  // delete all nil entries at the beginning of the packets slice
   151  func (h *sentPacketHistory) cleanupStart() {
   152  	for i, p := range h.packets {
   153  		if p != nil {
   154  			h.packets = h.packets[i:]
   155  			return
   156  		}
   157  	}
   158  	h.packets = h.packets[:0]
   159  }
   160  
   161  func (h *sentPacketHistory) LowestPacketNumber() protocol.PacketNumber {
   162  	if len(h.packets) == 0 {
   163  		return protocol.InvalidPacketNumber
   164  	}
   165  	return h.packets[0].PacketNumber
   166  }
   167  
   168  func (h *sentPacketHistory) DeclareLost(pn protocol.PacketNumber) {
   169  	idx, ok := h.getIndex(pn)
   170  	if !ok {
   171  		return
   172  	}
   173  	p := h.packets[idx]
   174  	if p.outstanding() {
   175  		h.numOutstanding--
   176  		if h.numOutstanding < 0 {
   177  			panic("negative number of outstanding packets")
   178  		}
   179  	}
   180  	h.packets[idx] = nil
   181  	if idx == 0 {
   182  		h.cleanupStart()
   183  	}
   184  }