From 0fb70387477b0b5b65afb1b04febfd5907d8da3f Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Fri, 22 Apr 2016 11:28:29 +0700 Subject: [PATCH] calculate expected entropy in seperate function for ReceivedAck --- ackhandler/outgoing_packet_ack_handler.go | 140 +++++++++++------- .../outgoing_packet_ack_handler_test.go | 3 + 2 files changed, 88 insertions(+), 55 deletions(-) diff --git a/ackhandler/outgoing_packet_ack_handler.go b/ackhandler/outgoing_packet_ack_handler.go index 4712a5af..89b15ca5 100644 --- a/ackhandler/outgoing_packet_ack_handler.go +++ b/ackhandler/outgoing_packet_ack_handler.go @@ -8,6 +8,11 @@ import ( "github.com/lucas-clemente/quic-go/protocol" ) +var ( + errEntropy = errors.New("OutgoingPacketAckHandler: Wrong entropy") + errMapAccess = errors.New("OutgoingPacketAckHandler: Packet does not exist in PacketHistory") +) + type outgoingPacketAckHandler struct { lastSentPacketNumber protocol.PacketNumber highestInOrderAckedPacketNumber protocol.PacketNumber @@ -52,6 +57,60 @@ func (h *outgoingPacketAckHandler) SentPacket(packet *Packet) error { return nil } +func (h *outgoingPacketAckHandler) calculateExpectedEntropy(ackFrame *frames.AckFrame) (EntropyAccumulator, error) { + h.packetHistoryMutex.Lock() + defer h.packetHistoryMutex.Unlock() + + highestInOrderAckedPacketNumber := ackFrame.GetHighestInOrderPacketNumber() + + var expectedEntropy EntropyAccumulator + + if !ackFrame.HasNACK() { // if the packet doesn't have NACKs, the correct entropy value is the entropy we sent the LargestObserved packet with. Just look it up in the map + packet, ok := h.packetHistory[ackFrame.LargestObserved] + if !ok { + return 0, errMapAccess + } + expectedEntropy = packet.Entropy + } else { // if the packet has NACKs, the entropy value has to be calculated + // get the entropy for the highestInOrderAckedPacketNumber + // There are two cases: + // 1. the packet with highestInOrderAckedPacketNumber has already been ACKed, then it doesn't exist in the packetHistory map anymore, but the value was saved as h.highestInOrderAckedEntropy + // 2. the packet with highestInOrderAckedPacketNumber has not yet been ACKed, then it should exist in the packetHistory map, and can just be read from there + if highestInOrderAckedPacketNumber == h.highestInOrderAckedPacketNumber { + expectedEntropy = h.highestInOrderAckedEntropy + } else { + packet, ok := h.packetHistory[highestInOrderAckedPacketNumber] + if !ok { + return 0, errMapAccess + } + expectedEntropy = packet.Entropy + } + + nackRangeIndex := len(ackFrame.NackRanges) - 1 + nackRange := ackFrame.NackRanges[nackRangeIndex] + for i := highestInOrderAckedPacketNumber + 1; i <= ackFrame.LargestObserved; i++ { + // select correct NACK range + if i > nackRange.LastPacketNumber { + nackRangeIndex-- + if nackRangeIndex >= 0 { + nackRange = ackFrame.NackRanges[nackRangeIndex] + } + } + if i >= nackRange.FirstPacketNumber && i <= nackRange.LastPacketNumber { // PacketNumber i is contained in a NACK range, it's entropyBit is irrelevant + continue + } + // PacketNumber i is not contained in a NACK range, it's entropyBit has to be considered + packet, ok := h.packetHistory[i] + if !ok { + return 0, errMapAccess + } + expectedEntropy.Add(i, packet.EntropyBit) + } + } + + return expectedEntropy, nil +} + func (h *outgoingPacketAckHandler) ReceivedAck(ackFrame *frames.AckFrame) error { if ackFrame.LargestObserved > h.lastSentPacketNumber { return errors.New("OutgoingPacketAckHandler: Received ACK for an unsent package") @@ -61,80 +120,50 @@ func (h *outgoingPacketAckHandler) ReceivedAck(ackFrame *frames.AckFrame) error return nil } - entropyError := errors.New("OutgoingPacketAckHandler: Wrong entropy") - mapAccessError := errors.New("OutgoingPacketAckHandler: Packet does not exist in PacketHistory") - - h.packetHistoryMutex.Lock() - defer h.packetHistoryMutex.Unlock() - - highestInOrderAckedEntropy := h.highestInOrderAckedEntropy - highestInOrderAckedPacketNumber := ackFrame.GetHighestInOrderPacketNumber() - for i := h.highestInOrderAckedPacketNumber + 1; i <= highestInOrderAckedPacketNumber; i++ { - packet, ok := h.packetHistory[i] - if !ok { - return mapAccessError - } - highestInOrderAckedEntropy.Add(packet.PacketNumber, packet.EntropyBit) + expectedEntropy, err := h.calculateExpectedEntropy(ackFrame) + if err != nil { + return err } - var expectedEntropy EntropyAccumulator - - if !ackFrame.HasNACK() { - packet, ok := h.packetHistory[ackFrame.LargestObserved] - if !ok { - return mapAccessError - } - expectedEntropy = packet.Entropy - } else { - if highestInOrderAckedPacketNumber == h.highestInOrderAckedPacketNumber { - expectedEntropy = h.highestInOrderAckedEntropy - } else { - packet, ok := h.packetHistory[highestInOrderAckedPacketNumber] - if !ok { - return mapAccessError - } - expectedEntropy = packet.Entropy - } - - nackRangeIndex := len(ackFrame.NackRanges) - 1 - nackRange := ackFrame.NackRanges[nackRangeIndex] - for i := highestInOrderAckedPacketNumber + 1; i <= ackFrame.LargestObserved; i++ { - if i > nackRange.LastPacketNumber { - nackRangeIndex-- - if nackRangeIndex >= 0 { - nackRange = ackFrame.NackRanges[nackRangeIndex] - } - } - if i >= nackRange.FirstPacketNumber && i <= nackRange.LastPacketNumber { - continue - } - packet, ok := h.packetHistory[i] - if !ok { - return mapAccessError - } - expectedEntropy.Add(i, packet.EntropyBit) - } - } - - if ackFrame.Entropy != byte(expectedEntropy) { - return entropyError + if byte(expectedEntropy) != ackFrame.Entropy { + return errEntropy } // Entropy ok. Now actually process the ACK packet + h.packetHistoryMutex.Lock() + defer h.packetHistoryMutex.Unlock() + + highestInOrderAckedPacketNumber := ackFrame.GetHighestInOrderPacketNumber() + highestInOrderAckedEntropy := h.highestInOrderAckedEntropy + + // if this ACK increases the highestInOrderAckedPacketNumber, the packet will be deleted from the packetHistory map, thus we need to save it's Entropy before doing so + if highestInOrderAckedPacketNumber > h.highestInOrderAckedPacketNumber { + packet, ok := h.packetHistory[highestInOrderAckedPacketNumber] + if !ok { + return errMapAccess + } + highestInOrderAckedEntropy = packet.Entropy + } + + // delete all packets below the highestInOrderAckedPacketNumber for i := h.highestInOrderAckedPacketNumber; i <= highestInOrderAckedPacketNumber; i++ { delete(h.packetHistory, i) } + // delete packets with a packet number higher than highestInOrderAckedPacketNumber that have already been ACKed + // this is the case if the PacketNumber is *not* contained in any of the NACK ranges if ackFrame.HasNACK() { nackRangeIndex := len(ackFrame.NackRanges) - 1 nackRange := ackFrame.NackRanges[nackRangeIndex] for i := highestInOrderAckedPacketNumber + 1; i <= ackFrame.LargestObserved; i++ { + // select correct NACK range if i > nackRange.LastPacketNumber { nackRangeIndex-- if nackRangeIndex >= 0 { nackRange = ackFrame.NackRanges[nackRangeIndex] } } + // PacketNumber i is not contained in a NACK range if i >= nackRange.FirstPacketNumber && i <= nackRange.LastPacketNumber { continue } @@ -144,6 +173,7 @@ func (h *outgoingPacketAckHandler) ReceivedAck(ackFrame *frames.AckFrame) error h.highestInOrderAckedPacketNumber = highestInOrderAckedPacketNumber h.highestInOrderAckedEntropy = highestInOrderAckedEntropy + return nil } diff --git a/ackhandler/outgoing_packet_ack_handler_test.go b/ackhandler/outgoing_packet_ack_handler_test.go index 5cc3ea41..10f3ad07 100644 --- a/ackhandler/outgoing_packet_ack_handler_test.go +++ b/ackhandler/outgoing_packet_ack_handler_test.go @@ -82,6 +82,7 @@ var _ = Describe("AckHandler", func() { var ( packets []*Packet ) + BeforeEach(func() { packets = []*Packet{ &Packet{PacketNumber: 1, Plaintext: []byte{0x13, 0x37}, EntropyBit: true}, @@ -134,6 +135,7 @@ var _ = Describe("AckHandler", func() { } err := handler.ReceivedAck(&ack) Expect(err).To(HaveOccurred()) + Expect(err).To(Equal(errEntropy)) Expect(handler.highestInOrderAckedPacketNumber).To(Equal(protocol.PacketNumber(0))) Expect(handler.highestInOrderAckedEntropy).To(Equal(EntropyAccumulator(0))) // nothing should be deleted from the packetHistory map @@ -232,6 +234,7 @@ var _ = Describe("AckHandler", func() { } err := handler.ReceivedAck(&ack) Expect(err).To(HaveOccurred()) + Expect(err).To(Equal(errEntropy)) Expect(handler.packetHistory).To(HaveKey(protocol.PacketNumber(1))) Expect(handler.packetHistory).To(HaveKey(protocol.PacketNumber(2))) })