golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/sent_packet_list.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.21 6 7 package quic 8 9 // A sentPacketList is a ring buffer of sentPackets. 10 // 11 // Processing an ack for a packet causes all older packets past a small threshold 12 // to be discarded (RFC 9002, Section 6.1.1), so the list of in-flight packets is 13 // not sparse and will contain at most a few acked/lost packets we no longer 14 // care about. 15 type sentPacketList struct { 16 nextNum packetNumber // next packet number to add to the buffer 17 off int // offset of first packet in the buffer 18 size int // number of packets 19 p []*sentPacket 20 } 21 22 // start is the first packet in the list. 23 func (s *sentPacketList) start() packetNumber { 24 return s.nextNum - packetNumber(s.size) 25 } 26 27 // end is one after the last packet in the list. 28 // If the list is empty, start == end. 29 func (s *sentPacketList) end() packetNumber { 30 return s.nextNum 31 } 32 33 // discard clears the list. 34 func (s *sentPacketList) discard() { 35 *s = sentPacketList{} 36 } 37 38 // add appends a packet to the list. 39 func (s *sentPacketList) add(sent *sentPacket) { 40 if s.nextNum != sent.num { 41 panic("inserting out-of-order packet") 42 } 43 s.nextNum++ 44 if s.size >= len(s.p) { 45 s.grow() 46 } 47 i := (s.off + s.size) % len(s.p) 48 s.size++ 49 s.p[i] = sent 50 } 51 52 // nth returns a packet by index. 53 func (s *sentPacketList) nth(n int) *sentPacket { 54 index := (s.off + n) % len(s.p) 55 return s.p[index] 56 } 57 58 // num returns a packet by number. 59 // It returns nil if the packet is not in the list. 60 func (s *sentPacketList) num(num packetNumber) *sentPacket { 61 i := int(num - s.start()) 62 if i < 0 || i >= s.size { 63 return nil 64 } 65 return s.nth(i) 66 } 67 68 // clean removes all acked or lost packets from the head of the list. 69 func (s *sentPacketList) clean() { 70 for s.size > 0 { 71 sent := s.p[s.off] 72 if !sent.acked && !sent.lost { 73 return 74 } 75 sent.recycle() 76 s.p[s.off] = nil 77 s.off = (s.off + 1) % len(s.p) 78 s.size-- 79 } 80 s.off = 0 81 } 82 83 // grow increases the buffer to hold more packaets. 84 func (s *sentPacketList) grow() { 85 newSize := len(s.p) * 2 86 if newSize == 0 { 87 newSize = 64 88 } 89 p := make([]*sentPacket, newSize) 90 for i := 0; i < s.size; i++ { 91 p[i] = s.nth(i) 92 } 93 s.p = p 94 s.off = 0 95 }