simplify the API of the retransmission queue (#4793)

This commit is contained in:
Marten Seemann
2025-04-19 16:35:16 +08:00
committed by GitHub
parent 7548cc069a
commit 02fea84c12
3 changed files with 120 additions and 119 deletions

View File

@@ -513,21 +513,17 @@ func (p *packetPacker) maybeGetCryptoPacket(
}
var s *cryptoStream
var handler ackhandler.FrameHandler
var hasRetransmission bool
//nolint:exhaustive // Initial and Handshake are the only two encryption levels here.
switch encLevel {
case protocol.EncryptionInitial:
s = p.initialStream
handler = p.retransmissionQueue.InitialAckHandler()
hasRetransmission = p.retransmissionQueue.HasInitialData()
case protocol.EncryptionHandshake:
s = p.handshakeStream
handler = p.retransmissionQueue.HandshakeAckHandler()
hasRetransmission = p.retransmissionQueue.HasHandshakeData()
}
hasData := s.HasData()
handler := p.retransmissionQueue.AckHandler(encLevel)
hasRetransmission := p.retransmissionQueue.HasData(encLevel)
var ack *wire.AckFrame
if ackAllowed {
ack = p.acks.GetAckFrame(encLevel, now, !hasRetransmission && !hasData)
@@ -552,21 +548,15 @@ func (p *packetPacker) maybeGetCryptoPacket(
maxPacketSize -= hdr.GetLength(v)
if hasRetransmission {
for {
var f ackhandler.Frame
//nolint:exhaustive // 0-RTT packets can't contain any retransmissions
switch encLevel {
case protocol.EncryptionInitial:
f.Frame = p.retransmissionQueue.GetInitialFrame(maxPacketSize, v)
f.Handler = p.retransmissionQueue.InitialAckHandler()
case protocol.EncryptionHandshake:
f.Frame = p.retransmissionQueue.GetHandshakeFrame(maxPacketSize, v)
f.Handler = p.retransmissionQueue.HandshakeAckHandler()
}
if f.Frame == nil {
frame := p.retransmissionQueue.GetFrame(encLevel, maxPacketSize, v)
if frame == nil {
break
}
pl.frames = append(pl.frames, f)
frameLen := f.Frame.Length(v)
pl.frames = append(pl.frames, ackhandler.Frame{
Frame: frame,
Handler: p.retransmissionQueue.AckHandler(encLevel),
})
frameLen := frame.Length(v)
pl.length += frameLen
maxPacketSize -= frameLen
}
@@ -578,18 +568,13 @@ func (p *packetPacker) maybeGetCryptoPacket(
return hdr, pl
}
func (p *packetPacker) maybeGetAppDataPacketFor0RTT(
sealer sealer,
maxPacketSize protocol.ByteCount,
now time.Time,
v protocol.Version,
) (*wire.ExtendedHeader, payload) {
func (p *packetPacker) maybeGetAppDataPacketFor0RTT(sealer sealer, maxSize protocol.ByteCount, now time.Time, v protocol.Version) (*wire.ExtendedHeader, payload) {
if p.perspective != protocol.PerspectiveClient {
return nil, payload{}
}
hdr := p.getLongHeader(protocol.Encryption0RTT, v)
maxPayloadSize := maxPacketSize - hdr.GetLength(v) - protocol.ByteCount(sealer.Overhead())
maxPayloadSize := maxSize - hdr.GetLength(v) - protocol.ByteCount(sealer.Overhead())
return hdr, p.maybeGetAppDataPacket(maxPayloadSize, false, false, now, v)
}
@@ -633,7 +618,7 @@ func (p *packetPacker) maybeGetAppDataPacket(
}
func (p *packetPacker) composeNextPacket(
maxFrameSize protocol.ByteCount,
maxPayloadSize protocol.ByteCount,
onlyAck, ackAllowed bool,
now time.Time,
v protocol.Version,
@@ -646,7 +631,7 @@ func (p *packetPacker) composeNextPacket(
}
hasData := p.framer.HasData()
hasRetransmission := p.retransmissionQueue.HasAppData()
hasRetransmission := p.retransmissionQueue.HasData(protocol.Encryption1RTT)
var hasAck bool
var pl payload
@@ -661,7 +646,7 @@ func (p *packetPacker) composeNextPacket(
if p.datagramQueue != nil {
if f := p.datagramQueue.Peek(); f != nil {
size := f.Length(v)
if size <= maxFrameSize-pl.length { // DATAGRAM frame fits
if size <= maxPayloadSize-pl.length { // DATAGRAM frame fits
pl.frames = append(pl.frames, ackhandler.Frame{Frame: f})
pl.length += size
p.datagramQueue.Pop()
@@ -681,15 +666,15 @@ func (p *packetPacker) composeNextPacket(
if hasRetransmission {
for {
remainingLen := maxFrameSize - pl.length
remainingLen := maxPayloadSize - pl.length
if remainingLen < protocol.MinStreamFrameSize {
break
}
f := p.retransmissionQueue.GetAppDataFrame(remainingLen, v)
f := p.retransmissionQueue.GetFrame(protocol.Encryption1RTT, remainingLen, v)
if f == nil {
break
}
pl.frames = append(pl.frames, ackhandler.Frame{Frame: f, Handler: p.retransmissionQueue.AppDataAckHandler()})
pl.frames = append(pl.frames, ackhandler.Frame{Frame: f, Handler: p.retransmissionQueue.AckHandler(protocol.Encryption1RTT)})
pl.length += f.Length(v)
}
}
@@ -697,7 +682,7 @@ func (p *packetPacker) composeNextPacket(
if hasData {
var lengthAdded protocol.ByteCount
startLen := len(pl.frames)
pl.frames, pl.streamFrames, lengthAdded = p.framer.Append(pl.frames, pl.streamFrames, maxFrameSize-pl.length, now, v)
pl.frames, pl.streamFrames, lengthAdded = p.framer.Append(pl.frames, pl.streamFrames, maxPayloadSize-pl.length, now, v)
pl.length += lengthAdded
// add handlers for the control frames that were added
for i := startLen; i < len(pl.frames); i++ {
@@ -709,7 +694,8 @@ func (p *packetPacker) composeNextPacket(
// Path probing is currently not supported, therefore we don't need to set the OnAcked callback yet.
// PATH_CHALLENGE and PATH_RESPONSE are never retransmitted.
default:
pl.frames[i].Handler = p.retransmissionQueue.AppDataAckHandler()
// we might be packing a 0-RTT packet, but we need to use the 1-RTT ack handler anyway
pl.frames[i].Handler = p.retransmissionQueue.AckHandler(protocol.Encryption1RTT)
}
}
}

View File

@@ -39,16 +39,17 @@ func (q *retransmissionQueue) addHandshake(f wire.Frame) {
q.handshake = append(q.handshake, f)
}
func (q *retransmissionQueue) HasInitialData() bool {
return len(q.initialCryptoData) > 0 || len(q.initial) > 0
}
func (q *retransmissionQueue) HasHandshakeData() bool {
return len(q.handshakeCryptoData) > 0 || len(q.handshake) > 0
}
func (q *retransmissionQueue) HasAppData() bool {
return len(q.appData) > 0
func (q *retransmissionQueue) HasData(encLevel protocol.EncryptionLevel) bool {
//nolint:exhaustive // 0-RTT data is retransmitted in 1-RTT packets.
switch encLevel {
case protocol.EncryptionInitial:
return len(q.initialCryptoData) > 0 || len(q.initial) > 0
case protocol.EncryptionHandshake:
return len(q.handshakeCryptoData) > 0 || len(q.handshake) > 0
case protocol.Encryption1RTT:
return len(q.appData) > 0
}
return false
}
func (q *retransmissionQueue) addAppData(f wire.Frame) {
@@ -58,7 +59,20 @@ func (q *retransmissionQueue) addAppData(f wire.Frame) {
q.appData = append(q.appData, f)
}
func (q *retransmissionQueue) GetInitialFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
func (q *retransmissionQueue) GetFrame(encLevel protocol.EncryptionLevel, maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
//nolint:exhaustive // 0-RTT packets can't contain retransmissions
switch encLevel {
case protocol.EncryptionInitial:
return q.getInitialFrame(maxLen, v)
case protocol.EncryptionHandshake:
return q.getHandshakeFrame(maxLen, v)
case protocol.Encryption1RTT:
return q.getAppDataFrame(maxLen, v)
}
return nil
}
func (q *retransmissionQueue) getInitialFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
if len(q.initialCryptoData) > 0 {
f := q.initialCryptoData[0]
newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, v)
@@ -81,7 +95,7 @@ func (q *retransmissionQueue) GetInitialFrame(maxLen protocol.ByteCount, v proto
return f
}
func (q *retransmissionQueue) GetHandshakeFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
func (q *retransmissionQueue) getHandshakeFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
if len(q.handshakeCryptoData) > 0 {
f := q.handshakeCryptoData[0]
newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, v)
@@ -104,7 +118,7 @@ func (q *retransmissionQueue) GetHandshakeFrame(maxLen protocol.ByteCount, v pro
return f
}
func (q *retransmissionQueue) GetAppDataFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
func (q *retransmissionQueue) getAppDataFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
if len(q.appData) == 0 {
return nil
}
@@ -130,16 +144,16 @@ func (q *retransmissionQueue) DropPackets(encLevel protocol.EncryptionLevel) {
}
}
func (q *retransmissionQueue) InitialAckHandler() ackhandler.FrameHandler {
return (*retransmissionQueueInitialAckHandler)(q)
}
func (q *retransmissionQueue) HandshakeAckHandler() ackhandler.FrameHandler {
return (*retransmissionQueueHandshakeAckHandler)(q)
}
func (q *retransmissionQueue) AppDataAckHandler() ackhandler.FrameHandler {
return (*retransmissionQueueAppDataAckHandler)(q)
func (q *retransmissionQueue) AckHandler(encLevel protocol.EncryptionLevel) ackhandler.FrameHandler {
switch encLevel {
case protocol.EncryptionInitial:
return (*retransmissionQueueInitialAckHandler)(q)
case protocol.EncryptionHandshake:
return (*retransmissionQueueHandshakeAckHandler)(q)
case protocol.Encryption0RTT, protocol.Encryption1RTT:
return (*retransmissionQueueAppDataAckHandler)(q)
}
return nil
}
type retransmissionQueueInitialAckHandler retransmissionQueue

View File

@@ -17,25 +17,25 @@ var _ = Describe("Retransmission queue", func() {
Context("Initial data", func() {
It("doesn't dequeue anything when it's empty", func() {
Expect(q.HasInitialData()).To(BeFalse())
Expect(q.GetInitialFrame(protocol.MaxByteCount, protocol.Version1)).To(BeNil())
Expect(q.HasData(protocol.EncryptionInitial)).To(BeFalse())
Expect(q.GetFrame(protocol.EncryptionInitial, protocol.MaxByteCount, protocol.Version1)).To(BeNil())
})
It("queues and retrieves a control frame", func() {
f := &wire.MaxDataFrame{MaximumData: 0x42}
q.addInitial(f)
Expect(q.HasInitialData()).To(BeTrue())
Expect(q.GetInitialFrame(f.Length(protocol.Version1)-1, protocol.Version1)).To(BeNil())
Expect(q.GetInitialFrame(f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasInitialData()).To(BeFalse())
Expect(q.HasData(protocol.EncryptionInitial)).To(BeTrue())
Expect(q.GetFrame(protocol.EncryptionInitial, f.Length(protocol.Version1)-1, protocol.Version1)).To(BeNil())
Expect(q.GetFrame(protocol.EncryptionInitial, f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasData(protocol.EncryptionInitial)).To(BeFalse())
})
It("queues and retrieves a CRYPTO frame", func() {
f := &wire.CryptoFrame{Data: []byte("foobar")}
q.addInitial(f)
Expect(q.HasInitialData()).To(BeTrue())
Expect(q.GetInitialFrame(f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasInitialData()).To(BeFalse())
Expect(q.HasData(protocol.EncryptionInitial)).To(BeTrue())
Expect(q.GetFrame(protocol.EncryptionInitial, f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasData(protocol.EncryptionInitial)).To(BeFalse())
})
It("returns split CRYPTO frames", func() {
@@ -44,30 +44,30 @@ var _ = Describe("Retransmission queue", func() {
Data: []byte("foobar"),
}
q.addInitial(f)
Expect(q.HasInitialData()).To(BeTrue())
f1 := q.GetInitialFrame(f.Length(protocol.Version1)-3, protocol.Version1)
Expect(q.HasData(protocol.EncryptionInitial)).To(BeTrue())
f1 := q.GetFrame(protocol.EncryptionInitial, f.Length(protocol.Version1)-3, protocol.Version1)
Expect(f1).ToNot(BeNil())
Expect(f1).To(BeAssignableToTypeOf(&wire.CryptoFrame{}))
Expect(f1.(*wire.CryptoFrame).Data).To(Equal([]byte("foo")))
Expect(f1.(*wire.CryptoFrame).Offset).To(Equal(protocol.ByteCount(100)))
Expect(q.HasInitialData()).To(BeTrue())
f2 := q.GetInitialFrame(protocol.MaxByteCount, protocol.Version1)
Expect(q.HasData(protocol.EncryptionInitial)).To(BeTrue())
f2 := q.GetFrame(protocol.EncryptionInitial, protocol.MaxByteCount, protocol.Version1)
Expect(f2).ToNot(BeNil())
Expect(f2).To(BeAssignableToTypeOf(&wire.CryptoFrame{}))
Expect(f2.(*wire.CryptoFrame).Data).To(Equal([]byte("bar")))
Expect(f2.(*wire.CryptoFrame).Offset).To(Equal(protocol.ByteCount(103)))
Expect(q.HasInitialData()).To(BeFalse())
Expect(q.HasData(protocol.EncryptionInitial)).To(BeFalse())
})
It("returns other frames when a CRYPTO frame wouldn't fit", func() {
f := &wire.CryptoFrame{Data: []byte("foobar")}
q.addInitial(f)
q.addInitial(&wire.PingFrame{})
f1 := q.GetInitialFrame(2, protocol.Version1) // too small for a CRYPTO frame
f1 := q.GetFrame(protocol.EncryptionInitial, 2, protocol.Version1) // too small for a CRYPTO frame
Expect(f1).ToNot(BeNil())
Expect(f1).To(BeAssignableToTypeOf(&wire.PingFrame{}))
Expect(q.HasInitialData()).To(BeTrue())
f2 := q.GetInitialFrame(protocol.MaxByteCount, protocol.Version1)
Expect(q.HasData(protocol.EncryptionInitial)).To(BeTrue())
f2 := q.GetFrame(protocol.EncryptionInitial, protocol.MaxByteCount, protocol.Version1)
Expect(f2).To(Equal(f))
})
@@ -76,49 +76,49 @@ var _ = Describe("Retransmission queue", func() {
f := &wire.CryptoFrame{Data: []byte("foobar")}
q.addInitial(f)
q.addInitial(cf)
Expect(q.HasInitialData()).To(BeTrue())
Expect(q.GetInitialFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
Expect(q.GetInitialFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(cf))
Expect(q.HasInitialData()).To(BeFalse())
Expect(q.HasData(protocol.EncryptionInitial)).To(BeTrue())
Expect(q.GetFrame(protocol.EncryptionInitial, protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
Expect(q.GetFrame(protocol.EncryptionInitial, protocol.MaxByteCount, protocol.Version1)).To(Equal(cf))
Expect(q.HasData(protocol.EncryptionInitial)).To(BeFalse())
})
It("drops all Initial frames", func() {
q.addInitial(&wire.CryptoFrame{Data: []byte("foobar")})
q.addInitial(&wire.MaxDataFrame{MaximumData: 0x42})
q.DropPackets(protocol.EncryptionInitial)
Expect(q.HasInitialData()).To(BeFalse())
Expect(q.GetInitialFrame(protocol.MaxByteCount, protocol.Version1)).To(BeNil())
Expect(q.HasData(protocol.EncryptionInitial)).To(BeFalse())
Expect(q.GetFrame(protocol.EncryptionInitial, protocol.MaxByteCount, protocol.Version1)).To(BeNil())
})
It("retransmits a frame", func() {
f := &wire.MaxDataFrame{MaximumData: 0x42}
q.InitialAckHandler().OnLost(f)
Expect(q.HasInitialData()).To(BeTrue())
Expect(q.GetInitialFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
q.AckHandler(protocol.EncryptionInitial).OnLost(f)
Expect(q.HasData(protocol.EncryptionInitial)).To(BeTrue())
Expect(q.GetFrame(protocol.EncryptionInitial, protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
})
})
Context("Handshake data", func() {
It("doesn't dequeue anything when it's empty", func() {
Expect(q.HasHandshakeData()).To(BeFalse())
Expect(q.GetHandshakeFrame(protocol.MaxByteCount, protocol.Version1)).To(BeNil())
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeFalse())
Expect(q.GetFrame(protocol.EncryptionHandshake, protocol.MaxByteCount, protocol.Version1)).To(BeNil())
})
It("queues and retrieves a control frame", func() {
f := &wire.MaxDataFrame{MaximumData: 0x42}
q.addHandshake(f)
Expect(q.HasHandshakeData()).To(BeTrue())
Expect(q.GetHandshakeFrame(f.Length(protocol.Version1)-1, protocol.Version1)).To(BeNil())
Expect(q.GetHandshakeFrame(f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasHandshakeData()).To(BeFalse())
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeTrue())
Expect(q.GetFrame(protocol.EncryptionHandshake, f.Length(protocol.Version1)-1, protocol.Version1)).To(BeNil())
Expect(q.GetFrame(protocol.EncryptionHandshake, f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeFalse())
})
It("queues and retrieves a CRYPTO frame", func() {
f := &wire.CryptoFrame{Data: []byte("foobar")}
q.addHandshake(f)
Expect(q.HasHandshakeData()).To(BeTrue())
Expect(q.GetHandshakeFrame(f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasHandshakeData()).To(BeFalse())
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeTrue())
Expect(q.GetFrame(protocol.EncryptionHandshake, f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeFalse())
})
It("returns split CRYPTO frames", func() {
@@ -127,30 +127,30 @@ var _ = Describe("Retransmission queue", func() {
Data: []byte("foobar"),
}
q.addHandshake(f)
Expect(q.HasHandshakeData()).To(BeTrue())
f1 := q.GetHandshakeFrame(f.Length(protocol.Version1)-3, protocol.Version1)
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeTrue())
f1 := q.GetFrame(protocol.EncryptionHandshake, f.Length(protocol.Version1)-3, protocol.Version1)
Expect(f1).ToNot(BeNil())
Expect(f1).To(BeAssignableToTypeOf(&wire.CryptoFrame{}))
Expect(f1.(*wire.CryptoFrame).Data).To(Equal([]byte("foo")))
Expect(f1.(*wire.CryptoFrame).Offset).To(Equal(protocol.ByteCount(100)))
Expect(q.HasHandshakeData()).To(BeTrue())
f2 := q.GetHandshakeFrame(protocol.MaxByteCount, protocol.Version1)
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeTrue())
f2 := q.GetFrame(protocol.EncryptionHandshake, protocol.MaxByteCount, protocol.Version1)
Expect(f2).ToNot(BeNil())
Expect(f2).To(BeAssignableToTypeOf(&wire.CryptoFrame{}))
Expect(f2.(*wire.CryptoFrame).Data).To(Equal([]byte("bar")))
Expect(f2.(*wire.CryptoFrame).Offset).To(Equal(protocol.ByteCount(103)))
Expect(q.HasHandshakeData()).To(BeFalse())
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeFalse())
})
It("returns other frames when a CRYPTO frame wouldn't fit", func() {
f := &wire.CryptoFrame{Data: []byte("foobar")}
q.addHandshake(f)
q.addHandshake(&wire.PingFrame{})
f1 := q.GetHandshakeFrame(2, protocol.Version1) // too small for a CRYPTO frame
f1 := q.GetFrame(protocol.EncryptionHandshake, 2, protocol.Version1) // too small for a CRYPTO frame
Expect(f1).ToNot(BeNil())
Expect(f1).To(BeAssignableToTypeOf(&wire.PingFrame{}))
Expect(q.HasHandshakeData()).To(BeTrue())
f2 := q.GetHandshakeFrame(protocol.MaxByteCount, protocol.Version1)
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeTrue())
f2 := q.GetFrame(protocol.EncryptionHandshake, protocol.MaxByteCount, protocol.Version1)
Expect(f2).To(Equal(f))
})
@@ -159,48 +159,49 @@ var _ = Describe("Retransmission queue", func() {
f := &wire.CryptoFrame{Data: []byte("foobar")}
q.addHandshake(f)
q.addHandshake(cf)
Expect(q.HasHandshakeData()).To(BeTrue())
Expect(q.GetHandshakeFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
Expect(q.GetHandshakeFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(cf))
Expect(q.HasHandshakeData()).To(BeFalse())
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeTrue())
Expect(q.GetFrame(protocol.EncryptionHandshake, protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
Expect(q.GetFrame(protocol.EncryptionHandshake, protocol.MaxByteCount, protocol.Version1)).To(Equal(cf))
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeFalse())
})
It("drops all Handshake frames", func() {
q.addHandshake(&wire.CryptoFrame{Data: []byte("foobar")})
q.addHandshake(&wire.MaxDataFrame{MaximumData: 0x42})
q.DropPackets(protocol.EncryptionHandshake)
Expect(q.HasHandshakeData()).To(BeFalse())
Expect(q.GetHandshakeFrame(protocol.MaxByteCount, protocol.Version1)).To(BeNil())
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeFalse())
Expect(q.GetFrame(protocol.EncryptionHandshake, protocol.MaxByteCount, protocol.Version1)).To(BeNil())
})
It("retransmits a frame", func() {
f := &wire.MaxDataFrame{MaximumData: 0x42}
q.HandshakeAckHandler().OnLost(f)
Expect(q.HasHandshakeData()).To(BeTrue())
Expect(q.GetHandshakeFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
q.AckHandler(protocol.EncryptionHandshake).OnLost(f)
Expect(q.HasData(protocol.EncryptionHandshake)).To(BeTrue())
Expect(q.GetFrame(protocol.EncryptionHandshake, protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
})
})
Context("Application data", func() {
It("doesn't dequeue anything when it's empty", func() {
Expect(q.GetAppDataFrame(protocol.MaxByteCount, protocol.Version1)).To(BeNil())
Expect(q.HasData(protocol.Encryption1RTT)).To(BeFalse())
Expect(q.GetFrame(protocol.Encryption1RTT, protocol.MaxByteCount, protocol.Version1)).To(BeNil())
})
It("queues and retrieves a control frame", func() {
f := &wire.MaxDataFrame{MaximumData: 0x42}
Expect(q.HasAppData()).To(BeFalse())
Expect(q.HasData(protocol.Encryption1RTT)).To(BeFalse())
q.addAppData(f)
Expect(q.HasAppData()).To(BeTrue())
Expect(q.GetAppDataFrame(f.Length(protocol.Version1)-1, protocol.Version1)).To(BeNil())
Expect(q.GetAppDataFrame(f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasAppData()).To(BeFalse())
Expect(q.HasData(protocol.Encryption1RTT)).To(BeTrue())
Expect(q.GetFrame(protocol.Encryption1RTT, f.Length(protocol.Version1)-1, protocol.Version1)).To(BeNil())
Expect(q.GetFrame(protocol.Encryption1RTT, f.Length(protocol.Version1), protocol.Version1)).To(Equal(f))
Expect(q.HasData(protocol.Encryption1RTT)).To(BeFalse())
})
It("retransmits a frame", func() {
f := &wire.MaxDataFrame{MaximumData: 0x42}
q.AppDataAckHandler().OnLost(f)
Expect(q.HasAppData()).To(BeTrue())
Expect(q.GetAppDataFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
q.AckHandler(protocol.Encryption1RTT).OnLost(f)
Expect(q.HasData(protocol.Encryption1RTT)).To(BeTrue())
Expect(q.GetFrame(protocol.Encryption1RTT, protocol.MaxByteCount, protocol.Version1)).To(Equal(f))
})
})
})