github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/internal/wire/stream_frame_test.go (about) 1 package wire 2 3 import ( 4 "bytes" 5 "io" 6 7 "github.com/metacubex/quic-go/internal/protocol" 8 "github.com/metacubex/quic-go/quicvarint" 9 10 . "github.com/onsi/ginkgo/v2" 11 . "github.com/onsi/gomega" 12 ) 13 14 var _ = Describe("STREAM frame", func() { 15 Context("when parsing", func() { 16 It("parses a frame with OFF bit", func() { 17 data := encodeVarInt(0x12345) // stream ID 18 data = append(data, encodeVarInt(0xdecafbad)...) // offset 19 data = append(data, []byte("foobar")...) 20 frame, l, err := parseStreamFrame(data, 0x8^0x4, protocol.Version1) 21 Expect(err).ToNot(HaveOccurred()) 22 Expect(frame.StreamID).To(Equal(protocol.StreamID(0x12345))) 23 Expect(frame.Data).To(Equal([]byte("foobar"))) 24 Expect(frame.Fin).To(BeFalse()) 25 Expect(frame.Offset).To(Equal(protocol.ByteCount(0xdecafbad))) 26 Expect(l).To(Equal(len(data))) 27 }) 28 29 It("respects the LEN when parsing the frame", func() { 30 data := encodeVarInt(0x12345) // stream ID 31 data = append(data, encodeVarInt(4)...) // data length 32 data = append(data, []byte("foobar")...) 33 frame, l, err := parseStreamFrame(data, 0x8^0x2, protocol.Version1) 34 Expect(err).ToNot(HaveOccurred()) 35 Expect(frame.StreamID).To(Equal(protocol.StreamID(0x12345))) 36 Expect(frame.Data).To(Equal([]byte("foob"))) 37 Expect(frame.Fin).To(BeFalse()) 38 Expect(frame.Offset).To(BeZero()) 39 Expect(l).To(Equal(len(data) - 2)) 40 }) 41 42 It("parses a frame with FIN bit", func() { 43 data := encodeVarInt(9) // stream ID 44 data = append(data, []byte("foobar")...) 45 frame, l, err := parseStreamFrame(data, 0x8^0x1, protocol.Version1) 46 Expect(err).ToNot(HaveOccurred()) 47 Expect(frame.StreamID).To(Equal(protocol.StreamID(9))) 48 Expect(frame.Data).To(Equal([]byte("foobar"))) 49 Expect(frame.Fin).To(BeTrue()) 50 Expect(frame.Offset).To(BeZero()) 51 Expect(l).To(Equal(len(data))) 52 }) 53 54 It("allows empty frames", func() { 55 data := encodeVarInt(0x1337) // stream ID 56 data = append(data, encodeVarInt(0x12345)...) // offset 57 f, l, err := parseStreamFrame(data, 0x8^0x4, protocol.Version1) 58 Expect(err).ToNot(HaveOccurred()) 59 Expect(f.StreamID).To(Equal(protocol.StreamID(0x1337))) 60 Expect(f.Offset).To(Equal(protocol.ByteCount(0x12345))) 61 Expect(f.Data).To(BeEmpty()) 62 Expect(f.Fin).To(BeFalse()) 63 Expect(l).To(Equal(len(data))) 64 }) 65 66 It("rejects frames that overflow the maximum offset", func() { 67 data := encodeVarInt(0x12345) // stream ID 68 data = append(data, encodeVarInt(uint64(protocol.MaxByteCount-5))...) // offset 69 data = append(data, []byte("foobar")...) 70 _, _, err := parseStreamFrame(data, 0x8^0x4, protocol.Version1) 71 Expect(err).To(MatchError("stream data overflows maximum offset")) 72 }) 73 74 It("rejects frames that claim to be longer than the packet buffer size", func() { 75 data := encodeVarInt(0x12345) // stream ID 76 data = append(data, encodeVarInt(uint64(protocol.MaxPacketBufferSize)+1)...) // data length 77 data = append(data, make([]byte, protocol.MaxPacketBufferSize+1)...) 78 _, _, err := parseStreamFrame(data, 0x8^0x2, protocol.Version1) 79 Expect(err).To(Equal(io.EOF)) 80 }) 81 82 It("rejects frames that claim to be longer than the remaining size", func() { 83 data := encodeVarInt(0x12345) // stream ID 84 data = append(data, encodeVarInt(7)...) // data length 85 data = append(data, []byte("foobar")...) 86 _, _, err := parseStreamFrame(data, 0x8^0x2, protocol.Version1) 87 Expect(err).To(Equal(io.EOF)) 88 }) 89 90 It("errors on EOFs", func() { 91 typ := uint64(0x8 ^ 0x4 ^ 0x2) 92 data := encodeVarInt(0x12345) // stream ID 93 data = append(data, encodeVarInt(0xdecafbad)...) // offset 94 data = append(data, encodeVarInt(6)...) // data length 95 data = append(data, []byte("foobar")...) 96 _, _, err := parseStreamFrame(data, typ, protocol.Version1) 97 Expect(err).NotTo(HaveOccurred()) 98 for i := range data { 99 _, _, err = parseStreamFrame(data[:i], typ, protocol.Version1) 100 Expect(err).To(HaveOccurred()) 101 } 102 }) 103 }) 104 105 Context("using the buffer", func() { 106 It("uses the buffer for long STREAM frames", func() { 107 data := encodeVarInt(0x12345) // stream ID 108 data = append(data, bytes.Repeat([]byte{'f'}, protocol.MinStreamFrameBufferSize)...) 109 frame, l, err := parseStreamFrame(data, 0x8, protocol.Version1) 110 Expect(err).ToNot(HaveOccurred()) 111 Expect(frame.StreamID).To(Equal(protocol.StreamID(0x12345))) 112 Expect(frame.Data).To(Equal(bytes.Repeat([]byte{'f'}, protocol.MinStreamFrameBufferSize))) 113 Expect(frame.DataLen()).To(BeEquivalentTo(protocol.MinStreamFrameBufferSize)) 114 Expect(frame.Fin).To(BeFalse()) 115 Expect(frame.fromPool).To(BeTrue()) 116 Expect(l).To(Equal(len(data))) 117 Expect(frame.PutBack).ToNot(Panic()) 118 }) 119 120 It("doesn't use the buffer for short STREAM frames", func() { 121 data := encodeVarInt(0x12345) // stream ID 122 data = append(data, bytes.Repeat([]byte{'f'}, protocol.MinStreamFrameBufferSize-1)...) 123 frame, l, err := parseStreamFrame(data, 0x8, protocol.Version1) 124 Expect(err).ToNot(HaveOccurred()) 125 Expect(frame.StreamID).To(Equal(protocol.StreamID(0x12345))) 126 Expect(frame.Data).To(Equal(bytes.Repeat([]byte{'f'}, protocol.MinStreamFrameBufferSize-1))) 127 Expect(frame.DataLen()).To(BeEquivalentTo(protocol.MinStreamFrameBufferSize - 1)) 128 Expect(frame.Fin).To(BeFalse()) 129 Expect(frame.fromPool).To(BeFalse()) 130 Expect(l).To(Equal(len(data))) 131 Expect(frame.PutBack).ToNot(Panic()) 132 }) 133 }) 134 135 Context("when writing", func() { 136 It("writes a frame without offset", func() { 137 f := &StreamFrame{ 138 StreamID: 0x1337, 139 Data: []byte("foobar"), 140 } 141 b, err := f.Append(nil, protocol.Version1) 142 Expect(err).ToNot(HaveOccurred()) 143 expected := []byte{0x8} 144 expected = append(expected, encodeVarInt(0x1337)...) // stream ID 145 expected = append(expected, []byte("foobar")...) 146 Expect(b).To(Equal(expected)) 147 }) 148 149 It("writes a frame with offset", func() { 150 f := &StreamFrame{ 151 StreamID: 0x1337, 152 Offset: 0x123456, 153 Data: []byte("foobar"), 154 } 155 b, err := f.Append(nil, protocol.Version1) 156 Expect(err).ToNot(HaveOccurred()) 157 expected := []byte{0x8 ^ 0x4} 158 expected = append(expected, encodeVarInt(0x1337)...) // stream ID 159 expected = append(expected, encodeVarInt(0x123456)...) // offset 160 expected = append(expected, []byte("foobar")...) 161 Expect(b).To(Equal(expected)) 162 }) 163 164 It("writes a frame with FIN bit", func() { 165 f := &StreamFrame{ 166 StreamID: 0x1337, 167 Offset: 0x123456, 168 Fin: true, 169 } 170 b, err := f.Append(nil, protocol.Version1) 171 Expect(err).ToNot(HaveOccurred()) 172 expected := []byte{0x8 ^ 0x4 ^ 0x1} 173 expected = append(expected, encodeVarInt(0x1337)...) // stream ID 174 expected = append(expected, encodeVarInt(0x123456)...) // offset 175 Expect(b).To(Equal(expected)) 176 }) 177 178 It("writes a frame with data length", func() { 179 f := &StreamFrame{ 180 StreamID: 0x1337, 181 Data: []byte("foobar"), 182 DataLenPresent: true, 183 } 184 b, err := f.Append(nil, protocol.Version1) 185 Expect(err).ToNot(HaveOccurred()) 186 expected := []byte{0x8 ^ 0x2} 187 expected = append(expected, encodeVarInt(0x1337)...) // stream ID 188 expected = append(expected, encodeVarInt(6)...) // data length 189 expected = append(expected, []byte("foobar")...) 190 Expect(b).To(Equal(expected)) 191 }) 192 193 It("writes a frame with data length and offset", func() { 194 f := &StreamFrame{ 195 StreamID: 0x1337, 196 Data: []byte("foobar"), 197 DataLenPresent: true, 198 Offset: 0x123456, 199 } 200 b, err := f.Append(nil, protocol.Version1) 201 Expect(err).ToNot(HaveOccurred()) 202 expected := []byte{0x8 ^ 0x4 ^ 0x2} 203 expected = append(expected, encodeVarInt(0x1337)...) // stream ID 204 expected = append(expected, encodeVarInt(0x123456)...) // offset 205 expected = append(expected, encodeVarInt(6)...) // data length 206 expected = append(expected, []byte("foobar")...) 207 Expect(b).To(Equal(expected)) 208 }) 209 210 It("refuses to write an empty frame without FIN", func() { 211 f := &StreamFrame{ 212 StreamID: 0x42, 213 Offset: 0x1337, 214 } 215 _, err := f.Append(nil, protocol.Version1) 216 Expect(err).To(MatchError("StreamFrame: attempting to write empty frame without FIN")) 217 }) 218 }) 219 220 Context("length", func() { 221 It("has the right length for a frame without offset and data length", func() { 222 f := &StreamFrame{ 223 StreamID: 0x1337, 224 Data: []byte("foobar"), 225 } 226 Expect(f.Length(protocol.Version1)).To(BeEquivalentTo(1 + quicvarint.Len(0x1337) + 6)) 227 }) 228 229 It("has the right length for a frame with offset", func() { 230 f := &StreamFrame{ 231 StreamID: 0x1337, 232 Offset: 0x42, 233 Data: []byte("foobar"), 234 } 235 Expect(f.Length(protocol.Version1)).To(BeEquivalentTo(1 + quicvarint.Len(0x1337) + quicvarint.Len(0x42) + 6)) 236 }) 237 238 It("has the right length for a frame with data length", func() { 239 f := &StreamFrame{ 240 StreamID: 0x1337, 241 Offset: 0x1234567, 242 DataLenPresent: true, 243 Data: []byte("foobar"), 244 } 245 Expect(f.Length(protocol.Version1)).To(BeEquivalentTo(1 + quicvarint.Len(0x1337) + quicvarint.Len(0x1234567) + quicvarint.Len(6) + 6)) 246 }) 247 }) 248 249 Context("max data length", func() { 250 const maxSize = 3000 251 252 It("always returns a data length such that the resulting frame has the right size, if data length is not present", func() { 253 data := make([]byte, maxSize) 254 f := &StreamFrame{ 255 StreamID: 0x1337, 256 Offset: 0xdeadbeef, 257 } 258 for i := 1; i < 3000; i++ { 259 f.Data = nil 260 maxDataLen := f.MaxDataLen(protocol.ByteCount(i), protocol.Version1) 261 if maxDataLen == 0 { // 0 means that no valid STREAM frame can be written 262 // check that writing a minimal size STREAM frame (i.e. with 1 byte data) is actually larger than the desired size 263 f.Data = []byte{0} 264 b, err := f.Append(nil, protocol.Version1) 265 Expect(err).ToNot(HaveOccurred()) 266 Expect(len(b)).To(BeNumerically(">", i)) 267 continue 268 } 269 f.Data = data[:int(maxDataLen)] 270 b, err := f.Append(nil, protocol.Version1) 271 Expect(err).ToNot(HaveOccurred()) 272 Expect(len(b)).To(Equal(i)) 273 } 274 }) 275 276 It("always returns a data length such that the resulting frame has the right size, if data length is present", func() { 277 data := make([]byte, maxSize) 278 f := &StreamFrame{ 279 StreamID: 0x1337, 280 Offset: 0xdeadbeef, 281 DataLenPresent: true, 282 } 283 var frameOneByteTooSmallCounter int 284 for i := 1; i < 3000; i++ { 285 f.Data = nil 286 maxDataLen := f.MaxDataLen(protocol.ByteCount(i), protocol.Version1) 287 if maxDataLen == 0 { // 0 means that no valid STREAM frame can be written 288 // check that writing a minimal size STREAM frame (i.e. with 1 byte data) is actually larger than the desired size 289 f.Data = []byte{0} 290 b, err := f.Append(nil, protocol.Version1) 291 Expect(err).ToNot(HaveOccurred()) 292 Expect(len(b)).To(BeNumerically(">", i)) 293 continue 294 } 295 f.Data = data[:int(maxDataLen)] 296 b, err := f.Append(nil, protocol.Version1) 297 Expect(err).ToNot(HaveOccurred()) 298 // There's *one* pathological case, where a data length of x can be encoded into 1 byte 299 // but a data lengths of x+1 needs 2 bytes 300 // In that case, it's impossible to create a STREAM frame of the desired size 301 if len(b) == i-1 { 302 frameOneByteTooSmallCounter++ 303 continue 304 } 305 Expect(len(b)).To(Equal(i)) 306 } 307 Expect(frameOneByteTooSmallCounter).To(Equal(1)) 308 }) 309 }) 310 311 Context("splitting", func() { 312 It("doesn't split if the frame is short enough", func() { 313 f := &StreamFrame{ 314 StreamID: 0x1337, 315 DataLenPresent: true, 316 Offset: 0xdeadbeef, 317 Data: make([]byte, 100), 318 } 319 frame, needsSplit := f.MaybeSplitOffFrame(f.Length(protocol.Version1), protocol.Version1) 320 Expect(needsSplit).To(BeFalse()) 321 Expect(frame).To(BeNil()) 322 Expect(f.DataLen()).To(BeEquivalentTo(100)) 323 frame, needsSplit = f.MaybeSplitOffFrame(f.Length(protocol.Version1)-1, protocol.Version1) 324 Expect(needsSplit).To(BeTrue()) 325 Expect(frame.DataLen()).To(BeEquivalentTo(99)) 326 f.PutBack() 327 }) 328 329 It("keeps the data len", func() { 330 f := &StreamFrame{ 331 StreamID: 0x1337, 332 DataLenPresent: true, 333 Data: make([]byte, 100), 334 } 335 frame, needsSplit := f.MaybeSplitOffFrame(66, protocol.Version1) 336 Expect(needsSplit).To(BeTrue()) 337 Expect(frame).ToNot(BeNil()) 338 Expect(f.DataLenPresent).To(BeTrue()) 339 Expect(frame.DataLenPresent).To(BeTrue()) 340 }) 341 342 It("adjusts the offset", func() { 343 f := &StreamFrame{ 344 StreamID: 0x1337, 345 Offset: 0x100, 346 Data: []byte("foobar"), 347 } 348 frame, needsSplit := f.MaybeSplitOffFrame(f.Length(protocol.Version1)-3, protocol.Version1) 349 Expect(needsSplit).To(BeTrue()) 350 Expect(frame).ToNot(BeNil()) 351 Expect(frame.Offset).To(Equal(protocol.ByteCount(0x100))) 352 Expect(frame.Data).To(Equal([]byte("foo"))) 353 Expect(f.Offset).To(Equal(protocol.ByteCount(0x100 + 3))) 354 Expect(f.Data).To(Equal([]byte("bar"))) 355 }) 356 357 It("preserves the FIN bit", func() { 358 f := &StreamFrame{ 359 StreamID: 0x1337, 360 Fin: true, 361 Offset: 0xdeadbeef, 362 Data: make([]byte, 100), 363 } 364 frame, needsSplit := f.MaybeSplitOffFrame(50, protocol.Version1) 365 Expect(needsSplit).To(BeTrue()) 366 Expect(frame).ToNot(BeNil()) 367 Expect(frame.Offset).To(BeNumerically("<", f.Offset)) 368 Expect(f.Fin).To(BeTrue()) 369 Expect(frame.Fin).To(BeFalse()) 370 }) 371 372 It("produces frames of the correct length, without data len", func() { 373 const size = 1000 374 f := &StreamFrame{ 375 StreamID: 0xdecafbad, 376 Offset: 0x1234, 377 Data: []byte{0}, 378 } 379 minFrameSize := f.Length(protocol.Version1) 380 for i := protocol.ByteCount(0); i < minFrameSize; i++ { 381 f, needsSplit := f.MaybeSplitOffFrame(i, protocol.Version1) 382 Expect(needsSplit).To(BeTrue()) 383 Expect(f).To(BeNil()) 384 } 385 for i := minFrameSize; i < size; i++ { 386 f.fromPool = false 387 f.Data = make([]byte, size) 388 f, needsSplit := f.MaybeSplitOffFrame(i, protocol.Version1) 389 Expect(needsSplit).To(BeTrue()) 390 Expect(f.Length(protocol.Version1)).To(Equal(i)) 391 } 392 }) 393 394 It("produces frames of the correct length, with data len", func() { 395 const size = 1000 396 f := &StreamFrame{ 397 StreamID: 0xdecafbad, 398 Offset: 0x1234, 399 DataLenPresent: true, 400 Data: []byte{0}, 401 } 402 minFrameSize := f.Length(protocol.Version1) 403 for i := protocol.ByteCount(0); i < minFrameSize; i++ { 404 f, needsSplit := f.MaybeSplitOffFrame(i, protocol.Version1) 405 Expect(needsSplit).To(BeTrue()) 406 Expect(f).To(BeNil()) 407 } 408 var frameOneByteTooSmallCounter int 409 for i := minFrameSize; i < size; i++ { 410 f.fromPool = false 411 f.Data = make([]byte, size) 412 newFrame, needsSplit := f.MaybeSplitOffFrame(i, protocol.Version1) 413 Expect(needsSplit).To(BeTrue()) 414 // There's *one* pathological case, where a data length of x can be encoded into 1 byte 415 // but a data lengths of x+1 needs 2 bytes 416 // In that case, it's impossible to create a STREAM frame of the desired size 417 if newFrame.Length(protocol.Version1) == i-1 { 418 frameOneByteTooSmallCounter++ 419 continue 420 } 421 Expect(newFrame.Length(protocol.Version1)).To(Equal(i)) 422 } 423 Expect(frameOneByteTooSmallCounter).To(Equal(1)) 424 }) 425 }) 426 })