bundle ACK frames when packing a packet

This commit is contained in:
Marten Seemann
2020-05-13 18:46:04 +07:00
parent fa381fffa0
commit 9177500096
8 changed files with 187 additions and 112 deletions

View File

@@ -135,12 +135,13 @@ type sealingManager interface {
}
type frameSource interface {
HasData() bool
AppendStreamFrames([]ackhandler.Frame, protocol.ByteCount) ([]ackhandler.Frame, protocol.ByteCount)
AppendControlFrames([]ackhandler.Frame, protocol.ByteCount) ([]ackhandler.Frame, protocol.ByteCount)
}
type ackFrameSource interface {
GetAckFrame(protocol.EncryptionLevel) *wire.AckFrame
GetAckFrame(encLevel protocol.EncryptionLevel, onlyIfQueued bool) *wire.AckFrame
}
type packetPacker struct {
@@ -279,18 +280,18 @@ func (p *packetPacker) MaybePackAckPacket(handshakeConfirmed bool) (*packedPacke
var encLevel protocol.EncryptionLevel
var ack *wire.AckFrame
if !handshakeConfirmed {
ack = p.acks.GetAckFrame(protocol.EncryptionInitial)
ack = p.acks.GetAckFrame(protocol.EncryptionInitial, true)
if ack != nil {
encLevel = protocol.EncryptionInitial
} else {
ack = p.acks.GetAckFrame(protocol.EncryptionHandshake)
ack = p.acks.GetAckFrame(protocol.EncryptionHandshake, true)
if ack != nil {
encLevel = protocol.EncryptionHandshake
}
}
}
if ack == nil {
ack = p.acks.GetAckFrame(protocol.Encryption1RTT)
ack = p.acks.GetAckFrame(protocol.Encryption1RTT, true)
if ack == nil {
return nil, nil
}
@@ -431,11 +432,12 @@ func (p *packetPacker) maybeAppendCryptoPacket(buffer *packetBuffer, maxPacketSi
}
}
hasData := s.HasData()
var ack *wire.AckFrame
if encLevel != protocol.EncryptionHandshake || buffer.Len() == 0 {
ack = p.acks.GetAckFrame(encLevel)
ack = p.acks.GetAckFrame(encLevel, !hasRetransmission && !hasData)
}
if !s.HasData() && !hasRetransmission && ack == nil {
if !hasData && !hasRetransmission && ack == nil {
// nothing to send
return nil, nil
}
@@ -499,7 +501,7 @@ func (p *packetPacker) maybeAppendAppDataPacket(buffer *packetBuffer, maxPacketS
headerLen := header.GetLength(p.version)
maxSize := maxPacketSize - buffer.Len() - protocol.ByteCount(sealer.Overhead()) - headerLen
payload := p.composeNextPacket(maxSize, encLevel != protocol.Encryption0RTT && buffer.Len() == 0)
payload := p.composeNextPacket(maxSize, encLevel == protocol.Encryption1RTT && buffer.Len() == 0)
// check if we have anything to send
if len(payload.frames) == 0 && payload.ack == nil {
@@ -523,35 +525,44 @@ func (p *packetPacker) maybeAppendAppDataPacket(buffer *packetBuffer, maxPacketS
func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, ackAllowed bool) payload {
var payload payload
var ack *wire.AckFrame
hasData := p.framer.HasData()
hasRetransmission := p.retransmissionQueue.HasAppData()
if ackAllowed {
ack = p.acks.GetAckFrame(protocol.Encryption1RTT)
ack = p.acks.GetAckFrame(protocol.Encryption1RTT, !hasRetransmission && !hasData)
if ack != nil {
payload.ack = ack
payload.length += ack.Length(p.version)
}
}
for {
remainingLen := maxFrameSize - payload.length
if remainingLen < protocol.MinStreamFrameSize {
break
}
f := p.retransmissionQueue.GetAppDataFrame(remainingLen)
if f == nil {
break
}
payload.frames = append(payload.frames, ackhandler.Frame{Frame: f})
payload.length += f.Length(p.version)
if ack == nil && !hasData && !hasRetransmission {
return payload
}
var lengthAdded protocol.ByteCount
payload.frames, lengthAdded = p.framer.AppendControlFrames(payload.frames, maxFrameSize-payload.length)
payload.length += lengthAdded
if hasRetransmission {
for {
remainingLen := maxFrameSize - payload.length
if remainingLen < protocol.MinStreamFrameSize {
break
}
f := p.retransmissionQueue.GetAppDataFrame(remainingLen)
if f == nil {
break
}
payload.frames = append(payload.frames, ackhandler.Frame{Frame: f})
payload.length += f.Length(p.version)
}
}
payload.frames, lengthAdded = p.framer.AppendStreamFrames(payload.frames, maxFrameSize-payload.length)
payload.length += lengthAdded
if hasData {
var lengthAdded protocol.ByteCount
payload.frames, lengthAdded = p.framer.AppendControlFrames(payload.frames, maxFrameSize-payload.length)
payload.length += lengthAdded
payload.frames, lengthAdded = p.framer.AppendStreamFrames(payload.frames, maxFrameSize-payload.length)
payload.length += lengthAdded
}
return payload
}