forked from quic-go/quic-go
90 lines
2.8 KiB
Go
90 lines
2.8 KiB
Go
package ackhandler
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
|
|
"github.com/lucas-clemente/quic-go/frames"
|
|
"github.com/lucas-clemente/quic-go/protocol"
|
|
)
|
|
|
|
type outgoingPacketAckHandler struct {
|
|
lastSentPacketNumber protocol.PacketNumber
|
|
highestInOrderAckedPacketNumber protocol.PacketNumber
|
|
highestInOrderAckedEntropy EntropyAccumulator
|
|
packetHistory map[protocol.PacketNumber]*Packet
|
|
packetHistoryMutex sync.Mutex
|
|
}
|
|
|
|
// NewOutgoingPacketAckHandler creates a new outgoingPacketAckHandler
|
|
func NewOutgoingPacketAckHandler() OutgoingPacketAckHandler {
|
|
return &outgoingPacketAckHandler{
|
|
packetHistory: make(map[protocol.PacketNumber]*Packet),
|
|
}
|
|
}
|
|
|
|
func (h *outgoingPacketAckHandler) SentPacket(packet *Packet) error {
|
|
h.packetHistoryMutex.Lock()
|
|
defer h.packetHistoryMutex.Unlock()
|
|
_, ok := h.packetHistory[packet.PacketNumber]
|
|
if ok {
|
|
return errors.New("Packet number already exists in Packet History")
|
|
}
|
|
if h.lastSentPacketNumber+1 != packet.PacketNumber {
|
|
return errors.New("Packet number must be increased by exactly 1")
|
|
}
|
|
|
|
var lastPacketEntropy EntropyAccumulator
|
|
if packet.PacketNumber == 1 {
|
|
lastPacketEntropy = EntropyAccumulator(0)
|
|
} else {
|
|
if h.highestInOrderAckedPacketNumber == packet.PacketNumber-1 {
|
|
lastPacketEntropy = h.highestInOrderAckedEntropy
|
|
} else {
|
|
lastPacketEntropy = h.packetHistory[packet.PacketNumber-1].Entropy
|
|
}
|
|
}
|
|
lastPacketEntropy.Add(packet.PacketNumber, packet.EntropyBit)
|
|
packet.Entropy = lastPacketEntropy
|
|
h.lastSentPacketNumber = packet.PacketNumber
|
|
h.packetHistory[packet.PacketNumber] = packet
|
|
return nil
|
|
}
|
|
|
|
func (h *outgoingPacketAckHandler) ReceivedAck(ackFrame *frames.AckFrame) error {
|
|
if ackFrame.LargestObserved > h.lastSentPacketNumber {
|
|
return errors.New("OutgoingPacketAckHandler: Received ACK for an unsent package")
|
|
}
|
|
|
|
entropyError := errors.New("OutgoingPacketAckHandler: Wrong entropy")
|
|
|
|
h.packetHistoryMutex.Lock()
|
|
defer h.packetHistoryMutex.Unlock()
|
|
|
|
highestInOrderAckedEntropy := h.highestInOrderAckedEntropy
|
|
highestInOrderAckedPacketNumber := ackFrame.GetHighestInOrderPacketNumber()
|
|
for i := h.highestInOrderAckedPacketNumber + 1; i <= highestInOrderAckedPacketNumber; i++ {
|
|
highestInOrderAckedEntropy.Add(h.packetHistory[i].PacketNumber, h.packetHistory[i].EntropyBit)
|
|
}
|
|
|
|
if !ackFrame.HasNACK() {
|
|
if ackFrame.Entropy != byte(h.packetHistory[ackFrame.LargestObserved].Entropy) {
|
|
return entropyError
|
|
}
|
|
}
|
|
// ToDo: check entropy for ACKs with NACKs
|
|
|
|
// Entropy ok. Now actually process the ACK packet
|
|
for i := h.highestInOrderAckedPacketNumber; i <= highestInOrderAckedPacketNumber; i++ {
|
|
delete(h.packetHistory, i)
|
|
}
|
|
|
|
h.highestInOrderAckedPacketNumber = highestInOrderAckedPacketNumber
|
|
h.highestInOrderAckedEntropy = highestInOrderAckedEntropy
|
|
return nil
|
|
}
|
|
|
|
func (h *outgoingPacketAckHandler) DequeuePacketForRetransmission() (packet *Packet) {
|
|
return nil
|
|
}
|