package ackhandler
import (
"iter"
"slices"
"github.com/tmc/go-iroh/internal/qng/internal/protocol"
)
type interval struct {
Start protocol .PacketNumber
End protocol .PacketNumber
}
type receivedPacketHistory struct {
ranges []interval
deletedBelow protocol .PacketNumber
}
func newReceivedPacketHistory() *receivedPacketHistory {
return &receivedPacketHistory {
deletedBelow : protocol .InvalidPacketNumber ,
}
}
func (h *receivedPacketHistory ) ReceivedPacket (p protocol .PacketNumber ) bool {
if p < h .deletedBelow {
return false
}
isNew := h .addToRanges (p )
if len (h .ranges ) > protocol .MaxNumAckRanges {
h .ranges = slices .Delete (h .ranges , 0 , len (h .ranges )-protocol .MaxNumAckRanges )
}
return isNew
}
func (h *receivedPacketHistory ) addToRanges (p protocol .PacketNumber ) bool {
if len (h .ranges ) == 0 {
h .ranges = append (h .ranges , interval {Start : p , End : p })
return true
}
for i := len (h .ranges ) - 1 ; i >= 0 ; i -- {
if p >= h .ranges [i ].Start && p <= h .ranges [i ].End {
return false
}
if h .ranges [i ].End == p -1 {
h .ranges [i ].End = p
return true
}
if h .ranges [i ].Start == p +1 {
h .ranges [i ].Start = p
if i > 0 && h .ranges [i -1 ].End +1 == h .ranges [i ].Start {
h .ranges [i -1 ].End = h .ranges [i ].End
h .ranges = slices .Delete (h .ranges , i , i +1 )
}
return true
}
if p > h .ranges [i ].End {
h .ranges = slices .Insert (h .ranges , i +1 , interval {Start : p , End : p })
return true
}
}
h .ranges = slices .Insert (h .ranges , 0 , interval {Start : p , End : p })
return true
}
func (h *receivedPacketHistory ) DeleteBelow (p protocol .PacketNumber ) {
if p < h .deletedBelow {
return
}
h .deletedBelow = p
if len (h .ranges ) == 0 {
return
}
idx := -1
for i := 0 ; i < len (h .ranges ); i ++ {
if h .ranges [i ].End < p {
idx = i
} else if p > h .ranges [i ].Start && p <= h .ranges [i ].End {
h .ranges [i ].Start = p
break
} else {
break
}
}
if idx >= 0 {
h .ranges = slices .Delete (h .ranges , 0 , idx +1 )
}
}
func (h *receivedPacketHistory ) Backward () iter .Seq [interval ] {
return func (yield func (interval ) bool ) {
for i := len (h .ranges ) - 1 ; i >= 0 ; i -- {
if !yield (h .ranges [i ]) {
return
}
}
}
}
func (h *receivedPacketHistory ) HighestMissingUpTo (p protocol .PacketNumber ) protocol .PacketNumber {
if len (h .ranges ) == 0 || (h .deletedBelow != protocol .InvalidPacketNumber && p < h .deletedBelow ) {
return protocol .InvalidPacketNumber
}
p = min (h .ranges [len (h .ranges )-1 ].End , p )
for i := len (h .ranges ) - 1 ; i >= 0 ; i -- {
r := h .ranges [i ]
if p >= r .Start && p <= r .End {
highest := r .Start - 1
if h .deletedBelow != protocol .InvalidPacketNumber && highest < h .deletedBelow {
return protocol .InvalidPacketNumber
}
return highest
}
if i >= 1 && p > h .ranges [i -1 ].End && p <= r .Start {
return p
}
}
return p
}
func (h *receivedPacketHistory ) IsPotentiallyDuplicate (p protocol .PacketNumber ) bool {
if p < h .deletedBelow {
return true
}
for i := len (h .ranges ) - 1 ; i >= 0 ; i -- {
if p > h .ranges [i ].End {
return false
}
if p <= h .ranges [i ].End && p >= h .ranges [i ].Start {
return true
}
}
return false
}
The pages are generated with Golds v0.8.4 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .