calculate expected entropy in seperate function for ReceivedAck

This commit is contained in:
Marten Seemann
2016-04-22 11:28:29 +07:00
parent e4bcf6f933
commit 0fb7038747
2 changed files with 88 additions and 55 deletions

View File

@@ -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
}