add a way to pack coalesced packets smaller than the usual packet size

This commit is contained in:
Marten Seemann
2020-04-22 17:00:28 +07:00
parent fd5ecee85d
commit 98233f6743
5 changed files with 113 additions and 53 deletions

View File

@@ -17,7 +17,7 @@ import (
)
type packer interface {
PackCoalescedPacket() (*coalescedPacket, error)
PackCoalescedPacket(protocol.ByteCount) (*coalescedPacket, error)
PackPacket() (*packedPacket, error)
MaybePackProbePacket(protocol.EncryptionLevel) (*packedPacket, error)
MaybePackAckPacket(handshakeConfirmed bool) (*packedPacket, error)
@@ -323,14 +323,14 @@ func (p *packetPacker) padPacket(buffer *packetBuffer) {
// PackCoalescedPacket packs a new packet.
// It packs an Initial / Handshake if there is data to send in these packet number spaces.
// It should only be called before the handshake is confirmed.
func (p *packetPacker) PackCoalescedPacket() (*coalescedPacket, error) {
func (p *packetPacker) PackCoalescedPacket(maxPacketSize protocol.ByteCount) (*coalescedPacket, error) {
buffer := getPacketBuffer()
packet, err := p.packCoalescedPacket(buffer)
packet, err := p.packCoalescedPacket(buffer, maxPacketSize)
if err != nil {
return nil, err
}
if len(packet.packets) == 0 { // nothing to send
if packet == nil || len(packet.packets) == 0 { // nothing to send
buffer.Release()
return nil, nil
}
@@ -342,37 +342,45 @@ func (p *packetPacker) PackCoalescedPacket() (*coalescedPacket, error) {
return packet, nil
}
func (p *packetPacker) packCoalescedPacket(buffer *packetBuffer) (*coalescedPacket, error) {
func (p *packetPacker) packCoalescedPacket(buffer *packetBuffer, maxPacketSize protocol.ByteCount) (*coalescedPacket, error) {
maxPacketSize = utils.MinByteCount(maxPacketSize, p.maxPacketSize)
if p.perspective == protocol.PerspectiveClient {
maxPacketSize = protocol.MinInitialPacketSize
}
if maxPacketSize < protocol.MinCoalescedPacketSize {
return nil, nil
}
packet := &coalescedPacket{
buffer: buffer,
packets: make([]*packetContents, 0, 3),
}
// Try packing an Initial packet.
contents, err := p.maybeAppendCryptoPacket(buffer, protocol.EncryptionInitial)
contents, err := p.maybeAppendCryptoPacket(buffer, maxPacketSize, protocol.EncryptionInitial)
if err != nil && err != handshake.ErrKeysDropped {
return nil, err
}
if contents != nil {
packet.packets = append(packet.packets, contents)
}
if buffer.Len() >= p.maxPacketSize-protocol.MinCoalescedPacketSize {
if buffer.Len() >= maxPacketSize-protocol.MinCoalescedPacketSize {
return packet, nil
}
// Add a Handshake packet.
contents, err = p.maybeAppendCryptoPacket(buffer, protocol.EncryptionHandshake)
contents, err = p.maybeAppendCryptoPacket(buffer, maxPacketSize, protocol.EncryptionHandshake)
if err != nil && err != handshake.ErrKeysDropped && err != handshake.ErrKeysNotYetAvailable {
return nil, err
}
if contents != nil {
packet.packets = append(packet.packets, contents)
}
if buffer.Len() >= p.maxPacketSize-protocol.MinCoalescedPacketSize {
if buffer.Len() >= maxPacketSize-protocol.MinCoalescedPacketSize {
return packet, nil
}
// Add a 0-RTT / 1-RTT packet.
contents, err = p.maybeAppendAppDataPacket(buffer)
contents, err = p.maybeAppendAppDataPacket(buffer, maxPacketSize)
if err == handshake.ErrKeysNotYetAvailable {
return packet, nil
}
@@ -389,7 +397,7 @@ func (p *packetPacker) packCoalescedPacket(buffer *packetBuffer) (*coalescedPack
// It should be called after the handshake is confirmed.
func (p *packetPacker) PackPacket() (*packedPacket, error) {
buffer := getPacketBuffer()
contents, err := p.maybeAppendAppDataPacket(buffer)
contents, err := p.maybeAppendAppDataPacket(buffer, p.maxPacketSize)
if err != nil || contents == nil {
buffer.Release()
return nil, err
@@ -400,16 +408,12 @@ func (p *packetPacker) PackPacket() (*packedPacket, error) {
}, nil
}
func (p *packetPacker) maybeAppendCryptoPacket(buffer *packetBuffer, encLevel protocol.EncryptionLevel) (*packetContents, error) {
func (p *packetPacker) maybeAppendCryptoPacket(buffer *packetBuffer, maxPacketSize protocol.ByteCount, encLevel protocol.EncryptionLevel) (*packetContents, error) {
var sealer sealer
var s cryptoStream
var hasRetransmission bool
maxPacketSize := p.maxPacketSize
switch encLevel {
case protocol.EncryptionInitial:
if p.perspective == protocol.PerspectiveClient {
maxPacketSize = protocol.MinInitialPacketSize
}
s = p.initialStream
hasRetransmission = p.retransmissionQueue.HasInitialData()
var err error
@@ -471,7 +475,7 @@ func (p *packetPacker) maybeAppendCryptoPacket(buffer *packetBuffer, encLevel pr
return p.appendPacket(buffer, hdr, payload, encLevel, sealer)
}
func (p *packetPacker) maybeAppendAppDataPacket(buffer *packetBuffer) (*packetContents, error) {
func (p *packetPacker) maybeAppendAppDataPacket(buffer *packetBuffer, maxPacketSize protocol.ByteCount) (*packetContents, error) {
var sealer sealer
var header *wire.ExtendedHeader
var encLevel protocol.EncryptionLevel
@@ -494,7 +498,7 @@ func (p *packetPacker) maybeAppendAppDataPacket(buffer *packetBuffer) (*packetCo
}
headerLen := header.GetLength(p.version)
maxSize := p.maxPacketSize - buffer.Len() - protocol.ByteCount(sealer.Overhead()) - headerLen
maxSize := maxPacketSize - buffer.Len() - protocol.ByteCount(sealer.Overhead()) - headerLen
payload := p.composeNextPacket(maxSize, encLevel != protocol.Encryption0RTT && buffer.Len() == 0)
// check if we have anything to send
@@ -557,11 +561,11 @@ func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel) (
buffer := getPacketBuffer()
switch encLevel {
case protocol.EncryptionInitial:
contents, err = p.maybeAppendCryptoPacket(buffer, protocol.EncryptionInitial)
contents, err = p.maybeAppendCryptoPacket(buffer, p.maxPacketSize, protocol.EncryptionInitial)
case protocol.EncryptionHandshake:
contents, err = p.maybeAppendCryptoPacket(buffer, protocol.EncryptionHandshake)
contents, err = p.maybeAppendCryptoPacket(buffer, p.maxPacketSize, protocol.EncryptionHandshake)
case protocol.Encryption1RTT:
contents, err = p.maybeAppendAppDataPacket(buffer)
contents, err = p.maybeAppendAppDataPacket(buffer, p.maxPacketSize)
default:
panic("unknown encryption level")
}