mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 20:27:35 +03:00
uTLS is not yet bumped to the new version, so this commit breaks the dependencies relationship by getting rid of the local replace.
177 lines
3.7 KiB
Go
177 lines
3.7 KiB
Go
package ackhandler
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/refraction-networking/uquic/internal/protocol"
|
|
)
|
|
|
|
type sentPacketHistory struct {
|
|
packets []*packet
|
|
|
|
numOutstanding int
|
|
|
|
highestPacketNumber protocol.PacketNumber
|
|
}
|
|
|
|
func newSentPacketHistory() *sentPacketHistory {
|
|
return &sentPacketHistory{
|
|
packets: make([]*packet, 0, 32),
|
|
highestPacketNumber: protocol.InvalidPacketNumber,
|
|
}
|
|
}
|
|
|
|
func (h *sentPacketHistory) checkSequentialPacketNumberUse(pn protocol.PacketNumber) {
|
|
if h.highestPacketNumber != protocol.InvalidPacketNumber {
|
|
if pn != h.highestPacketNumber+1 {
|
|
panic("non-sequential packet number use")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (h *sentPacketHistory) SkippedPacket(pn protocol.PacketNumber) {
|
|
h.checkSequentialPacketNumberUse(pn)
|
|
h.highestPacketNumber = pn
|
|
h.packets = append(h.packets, &packet{
|
|
PacketNumber: pn,
|
|
skippedPacket: true,
|
|
})
|
|
}
|
|
|
|
func (h *sentPacketHistory) SentNonAckElicitingPacket(pn protocol.PacketNumber) {
|
|
h.checkSequentialPacketNumberUse(pn)
|
|
h.highestPacketNumber = pn
|
|
if len(h.packets) > 0 {
|
|
h.packets = append(h.packets, nil)
|
|
}
|
|
}
|
|
|
|
func (h *sentPacketHistory) SentAckElicitingPacket(p *packet) {
|
|
h.checkSequentialPacketNumberUse(p.PacketNumber)
|
|
h.highestPacketNumber = p.PacketNumber
|
|
h.packets = append(h.packets, p)
|
|
if p.outstanding() {
|
|
h.numOutstanding++
|
|
}
|
|
}
|
|
|
|
// Iterate iterates through all packets.
|
|
func (h *sentPacketHistory) Iterate(cb func(*packet) (cont bool, err error)) error {
|
|
for _, p := range h.packets {
|
|
if p == nil {
|
|
continue
|
|
}
|
|
cont, err := cb(p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !cont {
|
|
return nil
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// FirstOutstanding returns the first outstanding packet.
|
|
func (h *sentPacketHistory) FirstOutstanding() *packet {
|
|
if !h.HasOutstandingPackets() {
|
|
return nil
|
|
}
|
|
for _, p := range h.packets {
|
|
if p != nil && p.outstanding() {
|
|
return p
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h *sentPacketHistory) Len() int {
|
|
return len(h.packets)
|
|
}
|
|
|
|
func (h *sentPacketHistory) Remove(pn protocol.PacketNumber) error {
|
|
idx, ok := h.getIndex(pn)
|
|
if !ok {
|
|
return fmt.Errorf("packet %d not found in sent packet history", pn)
|
|
}
|
|
p := h.packets[idx]
|
|
if p.outstanding() {
|
|
h.numOutstanding--
|
|
if h.numOutstanding < 0 {
|
|
panic("negative number of outstanding packets")
|
|
}
|
|
}
|
|
h.packets[idx] = nil
|
|
// clean up all skipped packets directly before this packet number
|
|
for idx > 0 {
|
|
idx--
|
|
p := h.packets[idx]
|
|
if p == nil || !p.skippedPacket {
|
|
break
|
|
}
|
|
h.packets[idx] = nil
|
|
}
|
|
if idx == 0 {
|
|
h.cleanupStart()
|
|
}
|
|
if len(h.packets) > 0 && h.packets[0] == nil {
|
|
panic("remove failed")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// getIndex gets the index of packet p in the packets slice.
|
|
func (h *sentPacketHistory) getIndex(p protocol.PacketNumber) (int, bool) {
|
|
if len(h.packets) == 0 {
|
|
return 0, false
|
|
}
|
|
first := h.packets[0].PacketNumber
|
|
if p < first {
|
|
return 0, false
|
|
}
|
|
index := int(p - first)
|
|
if index > len(h.packets)-1 {
|
|
return 0, false
|
|
}
|
|
return index, true
|
|
}
|
|
|
|
func (h *sentPacketHistory) HasOutstandingPackets() bool {
|
|
return h.numOutstanding > 0
|
|
}
|
|
|
|
// delete all nil entries at the beginning of the packets slice
|
|
func (h *sentPacketHistory) cleanupStart() {
|
|
for i, p := range h.packets {
|
|
if p != nil {
|
|
h.packets = h.packets[i:]
|
|
return
|
|
}
|
|
}
|
|
h.packets = h.packets[:0]
|
|
}
|
|
|
|
func (h *sentPacketHistory) LowestPacketNumber() protocol.PacketNumber {
|
|
if len(h.packets) == 0 {
|
|
return protocol.InvalidPacketNumber
|
|
}
|
|
return h.packets[0].PacketNumber
|
|
}
|
|
|
|
func (h *sentPacketHistory) DeclareLost(pn protocol.PacketNumber) {
|
|
idx, ok := h.getIndex(pn)
|
|
if !ok {
|
|
return
|
|
}
|
|
p := h.packets[idx]
|
|
if p.outstanding() {
|
|
h.numOutstanding--
|
|
if h.numOutstanding < 0 {
|
|
panic("negative number of outstanding packets")
|
|
}
|
|
}
|
|
h.packets[idx] = nil
|
|
if idx == 0 {
|
|
h.cleanupStart()
|
|
}
|
|
}
|