mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-04 12:47:36 +03:00
When an ACK for a packet that was retransmitted arrives, we don't need to retransmit the retransmission, even if it was lost.
218 lines
7.5 KiB
Go
218 lines
7.5 KiB
Go
package ackhandler
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/lucas-clemente/quic-go/internal/protocol"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("SentPacketHistory", func() {
|
|
var hist *sentPacketHistory
|
|
|
|
expectInHistory := func(packetNumbers []protocol.PacketNumber) {
|
|
ExpectWithOffset(1, hist.packetMap).To(HaveLen(len(packetNumbers)))
|
|
ExpectWithOffset(1, hist.packetList.Len()).To(Equal(len(packetNumbers)))
|
|
i := 0
|
|
hist.Iterate(func(p *Packet) (bool, error) {
|
|
pn := packetNumbers[i]
|
|
ExpectWithOffset(1, p.PacketNumber).To(Equal(pn))
|
|
ExpectWithOffset(1, hist.packetMap[pn].Value.PacketNumber).To(Equal(pn))
|
|
i++
|
|
return true, nil
|
|
})
|
|
}
|
|
|
|
BeforeEach(func() {
|
|
hist = newSentPacketHistory()
|
|
})
|
|
|
|
It("saves sent packets", func() {
|
|
hist.SentPacket(&Packet{PacketNumber: 1})
|
|
hist.SentPacket(&Packet{PacketNumber: 3})
|
|
hist.SentPacket(&Packet{PacketNumber: 4})
|
|
expectInHistory([]protocol.PacketNumber{1, 3, 4})
|
|
})
|
|
|
|
It("gets the length", func() {
|
|
hist.SentPacket(&Packet{PacketNumber: 1})
|
|
hist.SentPacket(&Packet{PacketNumber: 10})
|
|
Expect(hist.Len()).To(Equal(2))
|
|
})
|
|
|
|
Context("getting the first outstanding packet", func() {
|
|
It("gets nil, if there are no packets", func() {
|
|
Expect(hist.FirstOutstanding()).To(BeNil())
|
|
})
|
|
|
|
It("gets the first outstanding packet", func() {
|
|
hist.SentPacket(&Packet{PacketNumber: 2})
|
|
hist.SentPacket(&Packet{PacketNumber: 3})
|
|
front := hist.FirstOutstanding()
|
|
Expect(front).ToNot(BeNil())
|
|
Expect(front.PacketNumber).To(Equal(protocol.PacketNumber(2)))
|
|
})
|
|
|
|
It("gets the second packet if the first one is retransmitted", func() {
|
|
hist.SentPacket(&Packet{PacketNumber: 1})
|
|
hist.SentPacket(&Packet{PacketNumber: 3})
|
|
hist.SentPacket(&Packet{PacketNumber: 4})
|
|
front := hist.FirstOutstanding()
|
|
Expect(front).ToNot(BeNil())
|
|
Expect(front.PacketNumber).To(Equal(protocol.PacketNumber(1)))
|
|
// Queue the first packet for retransmission.
|
|
// The first outstanding packet should now be 3.
|
|
_, err := hist.QueuePacketForRetransmission(1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
front = hist.FirstOutstanding()
|
|
Expect(front).ToNot(BeNil())
|
|
Expect(front.PacketNumber).To(Equal(protocol.PacketNumber(3)))
|
|
})
|
|
|
|
It("gets the third packet if the first two are retransmitted", func() {
|
|
hist.SentPacket(&Packet{PacketNumber: 1})
|
|
hist.SentPacket(&Packet{PacketNumber: 3})
|
|
hist.SentPacket(&Packet{PacketNumber: 4})
|
|
front := hist.FirstOutstanding()
|
|
Expect(front).ToNot(BeNil())
|
|
Expect(front.PacketNumber).To(Equal(protocol.PacketNumber(1)))
|
|
// Queue the second packet for retransmission.
|
|
// The first outstanding packet should still be 3.
|
|
_, err := hist.QueuePacketForRetransmission(3)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
front = hist.FirstOutstanding()
|
|
Expect(front).ToNot(BeNil())
|
|
Expect(front.PacketNumber).To(Equal(protocol.PacketNumber(1)))
|
|
// Queue the first packet for retransmission.
|
|
// The first outstanding packet should still be 4.
|
|
_, err = hist.QueuePacketForRetransmission(1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
front = hist.FirstOutstanding()
|
|
Expect(front).ToNot(BeNil())
|
|
Expect(front.PacketNumber).To(Equal(protocol.PacketNumber(4)))
|
|
})
|
|
})
|
|
|
|
It("gets a packet by packet number", func() {
|
|
p := &Packet{PacketNumber: 2}
|
|
hist.SentPacket(p)
|
|
Expect(hist.GetPacket(2)).To(Equal(p))
|
|
})
|
|
|
|
It("returns nil if the packet doesn't exist", func() {
|
|
Expect(hist.GetPacket(1337)).To(BeNil())
|
|
})
|
|
|
|
It("removes packets", func() {
|
|
hist.SentPacket(&Packet{PacketNumber: 1})
|
|
hist.SentPacket(&Packet{PacketNumber: 4})
|
|
hist.SentPacket(&Packet{PacketNumber: 8})
|
|
err := hist.Remove(4)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
expectInHistory([]protocol.PacketNumber{1, 8})
|
|
})
|
|
|
|
It("errors when trying to remove a non existing packet", func() {
|
|
hist.SentPacket(&Packet{PacketNumber: 1})
|
|
err := hist.Remove(2)
|
|
Expect(err).To(MatchError("packet 2 not found in sent packet history"))
|
|
})
|
|
|
|
Context("iterating", func() {
|
|
BeforeEach(func() {
|
|
hist.SentPacket(&Packet{PacketNumber: 10})
|
|
hist.SentPacket(&Packet{PacketNumber: 14})
|
|
hist.SentPacket(&Packet{PacketNumber: 18})
|
|
})
|
|
|
|
It("iterates over all packets", func() {
|
|
var iterations []protocol.PacketNumber
|
|
err := hist.Iterate(func(p *Packet) (bool, error) {
|
|
iterations = append(iterations, p.PacketNumber)
|
|
return true, nil
|
|
})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(iterations).To(Equal([]protocol.PacketNumber{10, 14, 18}))
|
|
})
|
|
|
|
It("stops iterating", func() {
|
|
var iterations []protocol.PacketNumber
|
|
err := hist.Iterate(func(p *Packet) (bool, error) {
|
|
iterations = append(iterations, p.PacketNumber)
|
|
return p.PacketNumber != 14, nil
|
|
})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(iterations).To(Equal([]protocol.PacketNumber{10, 14}))
|
|
})
|
|
|
|
It("returns the error", func() {
|
|
testErr := errors.New("test error")
|
|
var iterations []protocol.PacketNumber
|
|
err := hist.Iterate(func(p *Packet) (bool, error) {
|
|
iterations = append(iterations, p.PacketNumber)
|
|
if p.PacketNumber == 14 {
|
|
return false, testErr
|
|
}
|
|
return true, nil
|
|
})
|
|
Expect(err).To(MatchError(testErr))
|
|
Expect(iterations).To(Equal([]protocol.PacketNumber{10, 14}))
|
|
})
|
|
})
|
|
|
|
Context("retransmissions", func() {
|
|
BeforeEach(func() {
|
|
for i := protocol.PacketNumber(1); i <= 5; i++ {
|
|
hist.SentPacket(&Packet{PacketNumber: i})
|
|
}
|
|
})
|
|
|
|
It("gets packets for retransmission", func() {
|
|
p, err := hist.QueuePacketForRetransmission(3)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(p.PacketNumber).To(Equal(protocol.PacketNumber(3)))
|
|
Expect(p.queuedForRetransmission).To(BeTrue())
|
|
Expect(p.retransmissionOf).To(BeZero())
|
|
Expect(p.isRetransmission).To(BeFalse())
|
|
Expect(p.retransmittedAs).To(BeNil())
|
|
})
|
|
|
|
It("errors if the packet was already queued for retransmission", func() {
|
|
p, err := hist.QueuePacketForRetransmission(5)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(p).ToNot(BeNil())
|
|
_, err = hist.QueuePacketForRetransmission(5)
|
|
Expect(err).To(MatchError("sent packet history BUG: packet 5 already queued for retransmission"))
|
|
})
|
|
|
|
It("errors if the packet doesn't exist", func() {
|
|
_, err := hist.QueuePacketForRetransmission(100)
|
|
Expect(err).To(MatchError("sent packet history: packet 100 not found"))
|
|
})
|
|
|
|
It("adds a sent packets as a retransmission", func() {
|
|
hist.SentPacketsAsRetransmission([]*Packet{{PacketNumber: 13}}, 2)
|
|
expectInHistory([]protocol.PacketNumber{1, 2, 3, 4, 5, 13})
|
|
Expect(hist.GetPacket(13).isRetransmission).To(BeTrue())
|
|
Expect(hist.GetPacket(13).retransmissionOf).To(Equal(protocol.PacketNumber(2)))
|
|
Expect(hist.GetPacket(2).retransmittedAs).To(Equal([]protocol.PacketNumber{13}))
|
|
})
|
|
|
|
It("adds multiple packets sent as a retransmission", func() {
|
|
hist.SentPacketsAsRetransmission([]*Packet{{PacketNumber: 13}, {PacketNumber: 15}}, 2)
|
|
expectInHistory([]protocol.PacketNumber{1, 2, 3, 4, 5, 13, 15})
|
|
Expect(hist.GetPacket(13).isRetransmission).To(BeTrue())
|
|
Expect(hist.GetPacket(13).retransmissionOf).To(Equal(protocol.PacketNumber(2)))
|
|
Expect(hist.GetPacket(15).retransmissionOf).To(Equal(protocol.PacketNumber(2)))
|
|
Expect(hist.GetPacket(2).retransmittedAs).To(Equal([]protocol.PacketNumber{13, 15}))
|
|
})
|
|
|
|
It("adds a packet as a normal packet if the retransmitted packet doesn't exist", func() {
|
|
hist.SentPacketsAsRetransmission([]*Packet{{PacketNumber: 13}}, 7)
|
|
expectInHistory([]protocol.PacketNumber{1, 2, 3, 4, 5, 13})
|
|
Expect(hist.GetPacket(13).isRetransmission).To(BeFalse())
|
|
Expect(hist.GetPacket(13).retransmissionOf).To(BeZero())
|
|
})
|
|
})
|
|
})
|