implement a StopWaitingManager

fixes #30
This commit is contained in:
Marten Seemann
2016-04-29 16:53:47 +07:00
parent 88a82be2fa
commit 74f7576391
8 changed files with 195 additions and 38 deletions

View File

@@ -24,3 +24,10 @@ type ReceivedPacketHandler interface {
DequeueAckFrame() *frames.AckFrame
}
type StopWaitingManager interface {
RegisterPacketForRetransmission(packet *Packet)
GetStopWaitingFrame() *frames.StopWaitingFrame
SentStopWaitingWithPacket(packetNumber protocol.PacketNumber)
ReceivedAckForPacketNumber(packetNumber protocol.PacketNumber)
}

View File

@@ -33,14 +33,16 @@ type sentPacketHandler struct {
packetHistory map[protocol.PacketNumber]*Packet
retransmissionQueue []*Packet // ToDo: use better data structure
stopWaitingManager StopWaitingManager
bytesInFlight uint64
}
// NewSentPacketHandler creates a new sentPacketHandler
func NewSentPacketHandler() SentPacketHandler {
func NewSentPacketHandler(stopWaitingManager StopWaitingManager) SentPacketHandler {
return &sentPacketHandler{
packetHistory: make(map[protocol.PacketNumber]*Packet),
packetHistory: make(map[protocol.PacketNumber]*Packet),
stopWaitingManager: stopWaitingManager,
}
}
@@ -49,6 +51,9 @@ func (h *sentPacketHandler) ackPacket(packetNumber protocol.PacketNumber) {
h.bytesInFlight -= packet.Length
}
delete(h.packetHistory, packetNumber)
// TODO: add tests
h.stopWaitingManager.ReceivedAckForPacketNumber(packetNumber)
}
func (h *sentPacketHandler) nackPacket(packetNumber protocol.PacketNumber) error {

View File

@@ -13,7 +13,8 @@ var _ = Describe("SentPacketHandler", func() {
var handler *sentPacketHandler
var streamFrame frames.StreamFrame
BeforeEach(func() {
handler = NewSentPacketHandler().(*sentPacketHandler)
stopWaitingManager := NewStopWaitingManager()
handler = NewSentPacketHandler(stopWaitingManager).(*sentPacketHandler)
streamFrame = frames.StreamFrame{
StreamID: 5,
Data: []byte{0x13, 0x37},

View File

@@ -0,0 +1,52 @@
package ackhandler
import (
"github.com/lucas-clemente/quic-go/frames"
"github.com/lucas-clemente/quic-go/protocol"
)
// StopWaitingManager manages StopWaitingFrames
type stopWaitingManager struct {
// sentStopWaitings map[protocol.PacketNumber]protocol.PacketNumber // map[LeastUnacked]stopWaitingSentWithPacketNumber
lastNewStopWaitingFirstSentWithPacketNumber protocol.PacketNumber
currentStopWaitingFrame *frames.StopWaitingFrame
currentStopWaitingFrameSent bool
}
// NewStopWaitingManager creates a new StopWaitingManager
func NewStopWaitingManager() StopWaitingManager {
return &stopWaitingManager{
currentStopWaitingFrame: nil,
}
}
// RegisterPacketForRetransmission prepares the StopWaitingFrame, if neccessary
func (h *stopWaitingManager) RegisterPacketForRetransmission(packet *Packet) {
if h.currentStopWaitingFrame == nil || h.currentStopWaitingFrame.LeastUnacked <= packet.PacketNumber { // <= because for StopWaitingFrames LeastUnacked = packet.PacketNumber + 1
h.currentStopWaitingFrame = &frames.StopWaitingFrame{
LeastUnacked: packet.PacketNumber + 1,
Entropy: byte(packet.Entropy), // TODO: do we have to send out the entropy of this packet or of the next packet, possible fix for #29
}
h.currentStopWaitingFrameSent = false
}
}
// GetStopWaitingFrame gets the StopWaitingFrame that needs to be sent. It returns nil if no StopWaitingFrame needs to be sent
func (h *stopWaitingManager) GetStopWaitingFrame() *frames.StopWaitingFrame {
return h.currentStopWaitingFrame
}
// SentStopWaitingWithPacket must be called after sending out a StopWaitingFrame with a packet
func (h *stopWaitingManager) SentStopWaitingWithPacket(packetNumber protocol.PacketNumber) {
if !h.currentStopWaitingFrameSent {
h.lastNewStopWaitingFirstSentWithPacketNumber = packetNumber
}
h.currentStopWaitingFrameSent = true
}
// ReceivedAckForPacketNumber should be called after receiving an ACK
func (h *stopWaitingManager) ReceivedAckForPacketNumber(packetNumber protocol.PacketNumber) {
if packetNumber >= h.lastNewStopWaitingFirstSentWithPacketNumber {
h.currentStopWaitingFrame = nil
}
}

View File

@@ -0,0 +1,77 @@
package ackhandler
import (
"github.com/lucas-clemente/quic-go/protocol"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("StopWaitingManager", func() {
var manager *stopWaitingManager
BeforeEach(func() {
manager = NewStopWaitingManager().(*stopWaitingManager)
})
It("returns nil in the beginning", func() {
Expect(manager.GetStopWaitingFrame()).To(BeNil())
})
It("gets a StopWaitingFrame after a packet has been registered for retransmission", func() {
leastUnacked := protocol.PacketNumber(10)
manager.RegisterPacketForRetransmission(&Packet{PacketNumber: leastUnacked, Entropy: 10})
swf := manager.GetStopWaitingFrame()
Expect(swf).ToNot(BeNil())
Expect(swf.LeastUnacked).To(Equal(leastUnacked + 1))
Expect(swf.Entropy).To(Equal(byte(10)))
})
It("always gets the StopWaitingFrame for the highest retransmitted packet number", func() {
leastUnacked := protocol.PacketNumber(10)
manager.RegisterPacketForRetransmission(&Packet{PacketNumber: leastUnacked, Entropy: 10})
manager.RegisterPacketForRetransmission(&Packet{PacketNumber: leastUnacked - 1, Entropy: 8})
swf := manager.GetStopWaitingFrame()
Expect(swf).ToNot(BeNil())
Expect(swf.LeastUnacked).To(Equal(leastUnacked + 1))
Expect(swf.Entropy).To(Equal(byte(10)))
})
It("updates the StopWaitingFrame when a packet with a higher packet number is retransmitted", func() {
leastUnacked := protocol.PacketNumber(10)
manager.RegisterPacketForRetransmission(&Packet{PacketNumber: leastUnacked - 1, Entropy: 10})
manager.RegisterPacketForRetransmission(&Packet{PacketNumber: leastUnacked, Entropy: 8})
swf := manager.GetStopWaitingFrame()
Expect(swf).ToNot(BeNil())
Expect(swf.LeastUnacked).To(Equal(leastUnacked + 1))
Expect(swf.Entropy).To(Equal(byte(8)))
})
Context("ACK handling", func() {
It("removes the current StopWaitingFrame when the first packet it was sent with is ACKed", func() {
manager.RegisterPacketForRetransmission(&Packet{PacketNumber: 10})
manager.SentStopWaitingWithPacket(13)
manager.SentStopWaitingWithPacket(14)
manager.SentStopWaitingWithPacket(15)
Expect(manager.GetStopWaitingFrame()).ToNot(BeNil())
manager.ReceivedAckForPacketNumber(13)
Expect(manager.GetStopWaitingFrame()).To(BeNil())
})
It("removes the current StopWaitingFrame when any packet it was sent with is ACKed", func() {
manager.RegisterPacketForRetransmission(&Packet{PacketNumber: 10})
manager.SentStopWaitingWithPacket(13)
manager.SentStopWaitingWithPacket(14)
manager.SentStopWaitingWithPacket(15)
Expect(manager.GetStopWaitingFrame()).ToNot(BeNil())
manager.ReceivedAckForPacketNumber(14)
Expect(manager.GetStopWaitingFrame()).To(BeNil())
})
It("does not remove the current StopWaitingFrame when a packet before the one containing the StopWaitingFrame is ACKed", func() {
manager.RegisterPacketForRetransmission(&Packet{PacketNumber: 10})
manager.SentStopWaitingWithPacket(13)
Expect(manager.GetStopWaitingFrame()).ToNot(BeNil())
manager.ReceivedAckForPacketNumber(12)
Expect(manager.GetStopWaitingFrame()).ToNot(BeNil())
})
})
})