diff --git a/ackhandler/stop_waiting_manager.go b/ackhandler/stop_waiting_manager.go index adbc08f66..bd265a5d7 100644 --- a/ackhandler/stop_waiting_manager.go +++ b/ackhandler/stop_waiting_manager.go @@ -9,6 +9,7 @@ import ( type stopWaitingManager struct { // sentStopWaitings map[protocol.PacketNumber]protocol.PacketNumber // map[LeastUnacked]stopWaitingSentWithPacketNumber lastNewStopWaitingFirstSentWithPacketNumber protocol.PacketNumber + maxRetransmittedPacketNumber protocol.PacketNumber currentStopWaitingFrame *frames.StopWaitingFrame currentStopWaitingFrameSent bool } @@ -22,11 +23,16 @@ func NewStopWaitingManager() StopWaitingManager { // RegisterPacketForRetransmission prepares the StopWaitingFrame, if necessary func (h *stopWaitingManager) RegisterPacketForRetransmission(packet *Packet) { + // out-of-order retransmission. A StopWaitingFrame with a higher LeastUnacked was already queued (or sent in the past), no need to send another one again + if packet.PacketNumber < h.maxRetransmittedPacketNumber { + return + } 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.maxRetransmittedPacketNumber = packet.PacketNumber h.currentStopWaitingFrameSent = false } } diff --git a/ackhandler/stop_waiting_manager_test.go b/ackhandler/stop_waiting_manager_test.go index c5f6e454f..551279e4f 100644 --- a/ackhandler/stop_waiting_manager_test.go +++ b/ackhandler/stop_waiting_manager_test.go @@ -45,6 +45,16 @@ var _ = Describe("StopWaitingManager", func() { Expect(swf.Entropy).To(Equal(byte(8))) }) + It("does not create a new StopWaitingFrame for an out-of-order retransmission", func() { + leastUnacked := protocol.PacketNumber(10) + manager.RegisterPacketForRetransmission(&Packet{PacketNumber: leastUnacked, Entropy: 8}) + manager.SentStopWaitingWithPacket(12) + manager.ReceivedAckForPacketNumber(12) + manager.RegisterPacketForRetransmission(&Packet{PacketNumber: leastUnacked - 1, Entropy: 10}) + swf := manager.GetStopWaitingFrame() + Expect(swf).To(BeNil()) + }) + 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})