mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-03-31 10:47:35 +03:00
uTLS is not yet bumped to the new version, so this commit breaks the dependencies relationship by getting rid of the local replace.
224 lines
8.4 KiB
Go
224 lines
8.4 KiB
Go
package quic
|
|
|
|
import (
|
|
"github.com/refraction-networking/uquic/internal/protocol"
|
|
"github.com/refraction-networking/uquic/internal/wire"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("Retransmission queue", func() {
|
|
var q *retransmissionQueue
|
|
|
|
BeforeEach(func() {
|
|
q = newRetransmissionQueue()
|
|
})
|
|
|
|
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())
|
|
})
|
|
|
|
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())
|
|
})
|
|
|
|
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())
|
|
})
|
|
|
|
It("returns split CRYPTO frames", func() {
|
|
f := &wire.CryptoFrame{
|
|
Offset: 100,
|
|
Data: []byte("foobar"),
|
|
}
|
|
q.addInitial(f)
|
|
Expect(q.HasInitialData()).To(BeTrue())
|
|
f1 := q.GetInitialFrame(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(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())
|
|
})
|
|
|
|
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
|
|
Expect(f1).ToNot(BeNil())
|
|
Expect(f1).To(BeAssignableToTypeOf(&wire.PingFrame{}))
|
|
Expect(q.HasInitialData()).To(BeTrue())
|
|
f2 := q.GetInitialFrame(protocol.MaxByteCount, protocol.Version1)
|
|
Expect(f2).To(Equal(f))
|
|
})
|
|
|
|
It("retrieves both a CRYPTO frame and a control frame", func() {
|
|
cf := &wire.MaxDataFrame{MaximumData: 0x42}
|
|
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())
|
|
})
|
|
|
|
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())
|
|
})
|
|
|
|
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))
|
|
})
|
|
|
|
It("adds a PING", func() {
|
|
q.AddPing(protocol.EncryptionInitial)
|
|
Expect(q.HasInitialData()).To(BeTrue())
|
|
Expect(q.GetInitialFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(&wire.PingFrame{}))
|
|
})
|
|
})
|
|
|
|
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())
|
|
})
|
|
|
|
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())
|
|
})
|
|
|
|
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())
|
|
})
|
|
|
|
It("returns split CRYPTO frames", func() {
|
|
f := &wire.CryptoFrame{
|
|
Offset: 100,
|
|
Data: []byte("foobar"),
|
|
}
|
|
q.addHandshake(f)
|
|
Expect(q.HasHandshakeData()).To(BeTrue())
|
|
f1 := q.GetHandshakeFrame(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(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())
|
|
})
|
|
|
|
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
|
|
Expect(f1).ToNot(BeNil())
|
|
Expect(f1).To(BeAssignableToTypeOf(&wire.PingFrame{}))
|
|
Expect(q.HasHandshakeData()).To(BeTrue())
|
|
f2 := q.GetHandshakeFrame(protocol.MaxByteCount, protocol.Version1)
|
|
Expect(f2).To(Equal(f))
|
|
})
|
|
|
|
It("retrieves both a CRYPTO frame and a control frame", func() {
|
|
cf := &wire.MaxDataFrame{MaximumData: 0x42}
|
|
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())
|
|
})
|
|
|
|
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())
|
|
})
|
|
|
|
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))
|
|
})
|
|
|
|
It("adds a PING", func() {
|
|
q.AddPing(protocol.EncryptionHandshake)
|
|
Expect(q.HasHandshakeData()).To(BeTrue())
|
|
Expect(q.GetHandshakeFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(&wire.PingFrame{}))
|
|
})
|
|
})
|
|
|
|
Context("Application data", func() {
|
|
It("doesn't dequeue anything when it's empty", func() {
|
|
Expect(q.GetAppDataFrame(protocol.MaxByteCount, protocol.Version1)).To(BeNil())
|
|
})
|
|
|
|
It("queues and retrieves a control frame", func() {
|
|
f := &wire.MaxDataFrame{MaximumData: 0x42}
|
|
Expect(q.HasAppData()).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())
|
|
})
|
|
|
|
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))
|
|
})
|
|
|
|
It("adds a PING", func() {
|
|
q.AddPing(protocol.Encryption1RTT)
|
|
Expect(q.HasAppData()).To(BeTrue())
|
|
Expect(q.GetAppDataFrame(protocol.MaxByteCount, protocol.Version1)).To(Equal(&wire.PingFrame{}))
|
|
})
|
|
})
|
|
})
|