dnscrypt-proxy/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go

161 lines
4.4 KiB
Go
Raw Normal View History

2022-07-21 18:50:10 +02:00
package ackhandler
import (
"fmt"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
2022-08-30 20:45:06 +02:00
list "github.com/lucas-clemente/quic-go/internal/utils/linkedlist"
2022-07-21 18:50:10 +02:00
)
type sentPacketHistory struct {
2022-08-30 20:45:06 +02:00
rttStats *utils.RTTStats
2022-10-24 10:20:25 +02:00
outstandingPacketList *list.List[*Packet]
etcPacketList *list.List[*Packet]
packetMap map[protocol.PacketNumber]*list.Element[*Packet]
2022-08-30 20:45:06 +02:00
highestSent protocol.PacketNumber
2022-07-21 18:50:10 +02:00
}
func newSentPacketHistory(rttStats *utils.RTTStats) *sentPacketHistory {
return &sentPacketHistory{
2022-08-30 20:45:06 +02:00
rttStats: rttStats,
2022-10-24 10:20:25 +02:00
outstandingPacketList: list.New[*Packet](),
etcPacketList: list.New[*Packet](),
packetMap: make(map[protocol.PacketNumber]*list.Element[*Packet]),
2022-08-30 20:45:06 +02:00
highestSent: protocol.InvalidPacketNumber,
2022-07-21 18:50:10 +02:00
}
}
2022-10-24 10:20:25 +02:00
func (h *sentPacketHistory) SentNonAckElicitingPacket(pn protocol.PacketNumber, encLevel protocol.EncryptionLevel, t time.Time) {
h.registerSentPacket(pn, encLevel, t)
}
func (h *sentPacketHistory) SentAckElicitingPacket(p *Packet) {
h.registerSentPacket(p.PacketNumber, p.EncryptionLevel, p.SendTime)
var el *list.Element[*Packet]
if p.outstanding() {
el = h.outstandingPacketList.PushBack(p)
} else {
el = h.etcPacketList.PushBack(p)
}
h.packetMap[p.PacketNumber] = el
}
func (h *sentPacketHistory) registerSentPacket(pn protocol.PacketNumber, encLevel protocol.EncryptionLevel, t time.Time) {
if pn <= h.highestSent {
2022-07-21 18:50:10 +02:00
panic("non-sequential packet number use")
}
// Skipped packet numbers.
2022-10-24 10:20:25 +02:00
for p := h.highestSent + 1; p < pn; p++ {
el := h.etcPacketList.PushBack(&Packet{
PacketNumber: p,
EncryptionLevel: encLevel,
SendTime: t,
2022-07-21 18:50:10 +02:00
skippedPacket: true,
})
2022-10-24 10:20:25 +02:00
h.packetMap[p] = el
2022-07-21 18:50:10 +02:00
}
2022-10-24 10:20:25 +02:00
h.highestSent = pn
2022-07-21 18:50:10 +02:00
}
// Iterate iterates through all packets.
func (h *sentPacketHistory) Iterate(cb func(*Packet) (cont bool, err error)) error {
cont := true
2022-08-30 20:45:06 +02:00
outstandingEl := h.outstandingPacketList.Front()
etcEl := h.etcPacketList.Front()
2022-10-24 10:20:25 +02:00
var el *list.Element[*Packet]
2022-08-30 20:45:06 +02:00
// whichever has the next packet number is returned first
for cont {
if outstandingEl == nil || (etcEl != nil && etcEl.Value.PacketNumber < outstandingEl.Value.PacketNumber) {
el = etcEl
} else {
el = outstandingEl
}
if el == nil {
return nil
}
if el == outstandingEl {
outstandingEl = outstandingEl.Next()
} else {
etcEl = etcEl.Next()
}
2022-07-21 18:50:10 +02:00
var err error
2022-10-24 10:20:25 +02:00
cont, err = cb(el.Value)
2022-07-21 18:50:10 +02:00
if err != nil {
return err
}
}
return nil
}
2022-08-30 20:45:06 +02:00
// FirstOutstanding returns the first outstanding packet.
2022-07-21 18:50:10 +02:00
func (h *sentPacketHistory) FirstOutstanding() *Packet {
2022-08-30 20:45:06 +02:00
el := h.outstandingPacketList.Front()
if el == nil {
return nil
2022-07-21 18:50:10 +02:00
}
2022-10-24 10:20:25 +02:00
return el.Value
2022-07-21 18:50:10 +02:00
}
func (h *sentPacketHistory) Len() int {
return len(h.packetMap)
}
func (h *sentPacketHistory) Remove(p protocol.PacketNumber) error {
el, ok := h.packetMap[p]
if !ok {
return fmt.Errorf("packet %d not found in sent packet history", p)
}
2022-08-30 20:45:06 +02:00
h.outstandingPacketList.Remove(el)
h.etcPacketList.Remove(el)
2022-07-21 18:50:10 +02:00
delete(h.packetMap, p)
return nil
}
func (h *sentPacketHistory) HasOutstandingPackets() bool {
2022-08-30 20:45:06 +02:00
return h.outstandingPacketList.Len() > 0
2022-07-21 18:50:10 +02:00
}
func (h *sentPacketHistory) DeleteOldPackets(now time.Time) {
maxAge := 3 * h.rttStats.PTO(false)
2022-10-24 10:20:25 +02:00
var nextEl *list.Element[*Packet]
2022-08-30 20:45:06 +02:00
// we don't iterate outstandingPacketList, as we should not delete outstanding packets.
// being outstanding for more than 3*PTO should only happen in the case of drastic RTT changes.
for el := h.etcPacketList.Front(); el != nil; el = nextEl {
2022-07-21 18:50:10 +02:00
nextEl = el.Next()
p := el.Value
if p.SendTime.After(now.Add(-maxAge)) {
break
}
delete(h.packetMap, p.PacketNumber)
2022-08-30 20:45:06 +02:00
h.etcPacketList.Remove(el)
}
}
func (h *sentPacketHistory) DeclareLost(p *Packet) *Packet {
el, ok := h.packetMap[p.PacketNumber]
if !ok {
return nil
}
// try to remove it from both lists, as we don't know which one it currently belongs to.
// Remove is a no-op for elements that are not in the list.
h.outstandingPacketList.Remove(el)
h.etcPacketList.Remove(el)
p.declaredLost = true
// move it to the correct position in the etc list (based on the packet number)
for el = h.etcPacketList.Back(); el != nil; el = el.Prev() {
if el.Value.PacketNumber < p.PacketNumber {
break
}
}
if el == nil {
2022-10-24 10:20:25 +02:00
el = h.etcPacketList.PushFront(p)
2022-08-30 20:45:06 +02:00
} else {
2022-10-24 10:20:25 +02:00
el = h.etcPacketList.InsertAfter(p, el)
2022-07-21 18:50:10 +02:00
}
2022-08-30 20:45:06 +02:00
h.packetMap[p.PacketNumber] = el
2022-10-24 10:20:25 +02:00
return el.Value
2022-07-21 18:50:10 +02:00
}