github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/crypto_stream_test.go (about) 1 package quic 2 3 import ( 4 "fmt" 5 6 "github.com/danielpfeifer02/quic-go-prio-packs/internal/protocol" 7 "github.com/danielpfeifer02/quic-go-prio-packs/internal/qerr" 8 "github.com/danielpfeifer02/quic-go-prio-packs/internal/wire" 9 10 . "github.com/onsi/ginkgo/v2" 11 . "github.com/onsi/gomega" 12 ) 13 14 var _ = Describe("Crypto Stream", func() { 15 var str cryptoStream 16 17 BeforeEach(func() { 18 str = newCryptoStream() 19 }) 20 21 Context("handling incoming data", func() { 22 It("handles in-order CRYPTO frames", func() { 23 Expect(str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("foo")})).To(Succeed()) 24 Expect(str.GetCryptoData()).To(Equal([]byte("foo"))) 25 Expect(str.GetCryptoData()).To(BeNil()) 26 Expect(str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("bar"), Offset: 3})).To(Succeed()) 27 Expect(str.GetCryptoData()).To(Equal([]byte("bar"))) 28 Expect(str.GetCryptoData()).To(BeNil()) 29 }) 30 31 It("errors if the frame exceeds the maximum offset", func() { 32 Expect(str.HandleCryptoFrame(&wire.CryptoFrame{ 33 Offset: protocol.MaxCryptoStreamOffset - 5, 34 Data: []byte("foobar"), 35 })).To(MatchError(&qerr.TransportError{ 36 ErrorCode: qerr.CryptoBufferExceeded, 37 ErrorMessage: fmt.Sprintf("received invalid offset %d on crypto stream, maximum allowed %d", protocol.MaxCryptoStreamOffset+1, protocol.MaxCryptoStreamOffset), 38 })) 39 }) 40 41 It("handles out-of-order CRYPTO frames", func() { 42 Expect(str.HandleCryptoFrame(&wire.CryptoFrame{Offset: 3, Data: []byte("bar")})).To(Succeed()) 43 Expect(str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("foo")})).To(Succeed()) 44 Expect(str.GetCryptoData()).To(Equal([]byte("foobar"))) 45 Expect(str.GetCryptoData()).To(BeNil()) 46 }) 47 48 Context("finishing", func() { 49 It("errors if there's still data to read after finishing", func() { 50 Expect(str.HandleCryptoFrame(&wire.CryptoFrame{ 51 Data: []byte("foobar"), 52 Offset: 10, 53 })).To(Succeed()) 54 Expect(str.Finish()).To(MatchError(&qerr.TransportError{ 55 ErrorCode: qerr.ProtocolViolation, 56 ErrorMessage: "encryption level changed, but crypto stream has more data to read", 57 })) 58 }) 59 60 It("works with reordered data", func() { 61 f1 := &wire.CryptoFrame{ 62 Data: []byte("foo"), 63 } 64 f2 := &wire.CryptoFrame{ 65 Offset: 3, 66 Data: []byte("bar"), 67 } 68 Expect(str.HandleCryptoFrame(f2)).To(Succeed()) 69 Expect(str.HandleCryptoFrame(f1)).To(Succeed()) 70 Expect(str.Finish()).To(Succeed()) 71 Expect(str.HandleCryptoFrame(f2)).To(Succeed()) 72 }) 73 74 It("rejects new crypto data after finishing", func() { 75 Expect(str.Finish()).To(Succeed()) 76 Expect(str.HandleCryptoFrame(&wire.CryptoFrame{ 77 Data: []byte("foo"), 78 })).To(MatchError(&qerr.TransportError{ 79 ErrorCode: qerr.ProtocolViolation, 80 ErrorMessage: "received crypto data after change of encryption level", 81 })) 82 }) 83 84 It("ignores crypto data below the maximum offset received before finishing", func() { 85 Expect(str.HandleCryptoFrame(&wire.CryptoFrame{ 86 Data: []byte("foobar"), 87 })).To(Succeed()) 88 Expect(str.GetCryptoData()).To(Equal([]byte("foobar"))) 89 Expect(str.Finish()).To(Succeed()) 90 Expect(str.HandleCryptoFrame(&wire.CryptoFrame{ 91 Offset: 2, 92 Data: []byte("foo"), 93 })).To(Succeed()) 94 }) 95 }) 96 }) 97 98 Context("writing data", func() { 99 It("says if it has data", func() { 100 Expect(str.HasData()).To(BeFalse()) 101 _, err := str.Write([]byte("foobar")) 102 Expect(err).ToNot(HaveOccurred()) 103 Expect(str.HasData()).To(BeTrue()) 104 }) 105 106 It("pops crypto frames", func() { 107 _, err := str.Write([]byte("foobar")) 108 Expect(err).ToNot(HaveOccurred()) 109 f := str.PopCryptoFrame(1000) 110 Expect(f).ToNot(BeNil()) 111 Expect(f.Offset).To(BeZero()) 112 Expect(f.Data).To(Equal([]byte("foobar"))) 113 }) 114 115 It("coalesces multiple writes", func() { 116 _, err := str.Write([]byte("foo")) 117 Expect(err).ToNot(HaveOccurred()) 118 _, err = str.Write([]byte("bar")) 119 Expect(err).ToNot(HaveOccurred()) 120 f := str.PopCryptoFrame(1000) 121 Expect(f).ToNot(BeNil()) 122 Expect(f.Offset).To(BeZero()) 123 Expect(f.Data).To(Equal([]byte("foobar"))) 124 }) 125 126 It("respects the maximum size", func() { 127 frameHeaderLen := (&wire.CryptoFrame{}).Length(protocol.Version1) 128 _, err := str.Write([]byte("foobar")) 129 Expect(err).ToNot(HaveOccurred()) 130 f := str.PopCryptoFrame(frameHeaderLen + 3) 131 Expect(f).ToNot(BeNil()) 132 Expect(f.Offset).To(BeZero()) 133 Expect(f.Data).To(Equal([]byte("foo"))) 134 f = str.PopCryptoFrame(frameHeaderLen + 3) 135 Expect(f).ToNot(BeNil()) 136 Expect(f.Offset).To(Equal(protocol.ByteCount(3))) 137 Expect(f.Data).To(Equal([]byte("bar"))) 138 }) 139 }) 140 })