// Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build go1.21 package quic // A sentPacketList is a ring buffer of sentPackets. // // Processing an ack for a packet causes all older packets past a small threshold // to be discarded (RFC 9002, Section 6.1.1), so the list of in-flight packets is // not sparse and will contain at most a few acked/lost packets we no longer // care about. type sentPacketList struct { nextNum packetNumber // next packet number to add to the buffer off int // offset of first packet in the buffer size int // number of packets p []*sentPacket } // start is the first packet in the list. func (s *sentPacketList) start() packetNumber { return s.nextNum - packetNumber(s.size) } // end is one after the last packet in the list. // If the list is empty, start == end. func (s *sentPacketList) end() packetNumber { return s.nextNum } // discard clears the list. func (s *sentPacketList) discard() { *s = sentPacketList{} } // add appends a packet to the list. func (s *sentPacketList) add(sent *sentPacket) { if s.nextNum != sent.num { panic("inserting out-of-order packet") } s.nextNum++ if s.size >= len(s.p) { s.grow() } i := (s.off + s.size) % len(s.p) s.size++ s.p[i] = sent } // nth returns a packet by index. func (s *sentPacketList) nth(n int) *sentPacket { index := (s.off + n) % len(s.p) return s.p[index] } // num returns a packet by number. // It returns nil if the packet is not in the list. func (s *sentPacketList) num(num packetNumber) *sentPacket { i := int(num - s.start()) if i < 0 || i >= s.size { return nil } return s.nth(i) } // clean removes all acked or lost packets from the head of the list. func (s *sentPacketList) clean() { for s.size > 0 { sent := s.p[s.off] if !sent.acked && !sent.lost { return } sent.recycle() s.p[s.off] = nil s.off = (s.off + 1) % len(s.p) s.size-- } s.off = 0 } // grow increases the buffer to hold more packaets. func (s *sentPacketList) grow() { newSize := len(s.p) * 2 if newSize == 0 { newSize = 64 } p := make([]*sentPacket, newSize) for i := 0; i < s.size; i++ { p[i] = s.nth(i) } s.p = p s.off = 0 }