github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/internal/wire/frame_parser_test.go (about) 1 package wire 2 3 import ( 4 "time" 5 6 "github.com/apernet/quic-go/internal/protocol" 7 "github.com/apernet/quic-go/internal/qerr" 8 9 . "github.com/onsi/ginkgo/v2" 10 . "github.com/onsi/gomega" 11 ) 12 13 var _ = Describe("Frame parsing", func() { 14 var parser FrameParser 15 16 BeforeEach(func() { 17 parser = *NewFrameParser(true) 18 }) 19 20 It("returns nil if there's nothing more to read", func() { 21 l, f, err := parser.ParseNext(nil, protocol.Encryption1RTT, protocol.Version1) 22 Expect(err).ToNot(HaveOccurred()) 23 Expect(l).To(BeZero()) 24 Expect(f).To(BeNil()) 25 }) 26 27 It("skips PADDING frames", func() { 28 b := []byte{0, 0} // 2 PADDING frames 29 b, err := (&PingFrame{}).Append(b, protocol.Version1) 30 Expect(err).ToNot(HaveOccurred()) 31 l, f, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 32 Expect(err).ToNot(HaveOccurred()) 33 Expect(f).To(Equal(&PingFrame{})) 34 Expect(l).To(Equal(2 + 1)) 35 }) 36 37 It("handles PADDING at the end", func() { 38 l, f, err := parser.ParseNext([]byte{0, 0, 0}, protocol.Encryption1RTT, protocol.Version1) 39 Expect(err).ToNot(HaveOccurred()) 40 Expect(f).To(BeNil()) 41 Expect(l).To(Equal(3)) 42 }) 43 44 It("parses a single frame", func() { 45 var b []byte 46 for i := 0; i < 10; i++ { 47 var err error 48 b, err = (&PingFrame{}).Append(b, protocol.Version1) 49 Expect(err).ToNot(HaveOccurred()) 50 } 51 l, f, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 52 Expect(err).ToNot(HaveOccurred()) 53 Expect(f).To(BeAssignableToTypeOf(&PingFrame{})) 54 Expect(l).To(Equal(1)) 55 }) 56 57 It("unpacks ACK frames", func() { 58 f := &AckFrame{AckRanges: []AckRange{{Smallest: 1, Largest: 0x13}}} 59 b, err := f.Append(nil, protocol.Version1) 60 Expect(err).ToNot(HaveOccurred()) 61 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 62 Expect(err).ToNot(HaveOccurred()) 63 Expect(frame).ToNot(BeNil()) 64 Expect(frame).To(BeAssignableToTypeOf(f)) 65 Expect(frame.(*AckFrame).LargestAcked()).To(Equal(protocol.PacketNumber(0x13))) 66 Expect(l).To(Equal(len(b))) 67 }) 68 69 It("uses the custom ack delay exponent for 1RTT packets", func() { 70 parser.SetAckDelayExponent(protocol.AckDelayExponent + 2) 71 f := &AckFrame{ 72 AckRanges: []AckRange{{Smallest: 1, Largest: 1}}, 73 DelayTime: time.Second, 74 } 75 b, err := f.Append(nil, protocol.Version1) 76 Expect(err).ToNot(HaveOccurred()) 77 _, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 78 Expect(err).ToNot(HaveOccurred()) 79 // The ACK frame is always written using the protocol.AckDelayExponent. 80 // That's why we expect a different value when parsing. 81 Expect(frame.(*AckFrame).DelayTime).To(Equal(4 * time.Second)) 82 }) 83 84 It("uses the default ack delay exponent for non-1RTT packets", func() { 85 parser.SetAckDelayExponent(protocol.AckDelayExponent + 2) 86 f := &AckFrame{ 87 AckRanges: []AckRange{{Smallest: 1, Largest: 1}}, 88 DelayTime: time.Second, 89 } 90 b, err := f.Append(nil, protocol.Version1) 91 Expect(err).ToNot(HaveOccurred()) 92 _, frame, err := parser.ParseNext(b, protocol.EncryptionHandshake, protocol.Version1) 93 Expect(err).ToNot(HaveOccurred()) 94 Expect(frame.(*AckFrame).DelayTime).To(Equal(time.Second)) 95 }) 96 97 It("unpacks RESET_STREAM frames", func() { 98 f := &ResetStreamFrame{ 99 StreamID: 0xdeadbeef, 100 FinalSize: 0xdecafbad1234, 101 ErrorCode: 0x1337, 102 } 103 b, err := f.Append(nil, protocol.Version1) 104 Expect(err).ToNot(HaveOccurred()) 105 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 106 Expect(err).ToNot(HaveOccurred()) 107 Expect(frame).To(Equal(f)) 108 Expect(l).To(Equal(len(b))) 109 }) 110 111 It("unpacks STOP_SENDING frames", func() { 112 f := &StopSendingFrame{StreamID: 0x42} 113 b, err := f.Append(nil, protocol.Version1) 114 Expect(err).ToNot(HaveOccurred()) 115 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 116 Expect(err).ToNot(HaveOccurred()) 117 Expect(frame).To(Equal(f)) 118 Expect(l).To(Equal(len(b))) 119 }) 120 121 It("unpacks CRYPTO frames", func() { 122 f := &CryptoFrame{ 123 Offset: 0x1337, 124 Data: []byte("lorem ipsum"), 125 } 126 b, err := f.Append(nil, protocol.Version1) 127 Expect(err).ToNot(HaveOccurred()) 128 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 129 Expect(err).ToNot(HaveOccurred()) 130 Expect(frame).ToNot(BeNil()) 131 Expect(frame).To(Equal(f)) 132 Expect(l).To(Equal(len(b))) 133 }) 134 135 It("unpacks NEW_TOKEN frames", func() { 136 f := &NewTokenFrame{Token: []byte("foobar")} 137 b, err := f.Append(nil, protocol.Version1) 138 Expect(err).ToNot(HaveOccurred()) 139 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 140 Expect(err).ToNot(HaveOccurred()) 141 Expect(frame).ToNot(BeNil()) 142 Expect(frame).To(Equal(f)) 143 Expect(l).To(Equal(len(b))) 144 }) 145 146 It("unpacks STREAM frames", func() { 147 f := &StreamFrame{ 148 StreamID: 0x42, 149 Offset: 0x1337, 150 Fin: true, 151 Data: []byte("foobar"), 152 } 153 b, err := f.Append(nil, protocol.Version1) 154 Expect(err).ToNot(HaveOccurred()) 155 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 156 Expect(err).ToNot(HaveOccurred()) 157 Expect(frame).ToNot(BeNil()) 158 Expect(frame).To(Equal(f)) 159 Expect(l).To(Equal(len(b))) 160 }) 161 162 It("unpacks MAX_DATA frames", func() { 163 f := &MaxDataFrame{ 164 MaximumData: 0xcafe, 165 } 166 b, err := f.Append(nil, protocol.Version1) 167 Expect(err).ToNot(HaveOccurred()) 168 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 169 Expect(err).ToNot(HaveOccurred()) 170 Expect(frame).To(Equal(f)) 171 Expect(l).To(Equal(len(b))) 172 }) 173 174 It("unpacks MAX_STREAM_DATA frames", func() { 175 f := &MaxStreamDataFrame{ 176 StreamID: 0xdeadbeef, 177 MaximumStreamData: 0xdecafbad, 178 } 179 b, err := f.Append(nil, protocol.Version1) 180 Expect(err).ToNot(HaveOccurred()) 181 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 182 Expect(err).ToNot(HaveOccurred()) 183 Expect(frame).To(Equal(f)) 184 Expect(l).To(Equal(len(b))) 185 }) 186 187 It("unpacks MAX_STREAMS frames", func() { 188 f := &MaxStreamsFrame{ 189 Type: protocol.StreamTypeBidi, 190 MaxStreamNum: 0x1337, 191 } 192 b, err := f.Append(nil, protocol.Version1) 193 Expect(err).ToNot(HaveOccurred()) 194 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 195 Expect(err).ToNot(HaveOccurred()) 196 Expect(frame).To(Equal(f)) 197 Expect(l).To(Equal(len(b))) 198 }) 199 200 It("unpacks DATA_BLOCKED frames", func() { 201 f := &DataBlockedFrame{MaximumData: 0x1234} 202 b, err := f.Append(nil, protocol.Version1) 203 Expect(err).ToNot(HaveOccurred()) 204 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 205 Expect(err).ToNot(HaveOccurred()) 206 Expect(frame).To(Equal(f)) 207 Expect(l).To(Equal(len(b))) 208 }) 209 210 It("unpacks STREAM_DATA_BLOCKED frames", func() { 211 f := &StreamDataBlockedFrame{ 212 StreamID: 0xdeadbeef, 213 MaximumStreamData: 0xdead, 214 } 215 b, err := f.Append(nil, protocol.Version1) 216 Expect(err).ToNot(HaveOccurred()) 217 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 218 Expect(err).ToNot(HaveOccurred()) 219 Expect(frame).To(Equal(f)) 220 Expect(l).To(Equal(len(b))) 221 }) 222 223 It("unpacks STREAMS_BLOCKED frames", func() { 224 f := &StreamsBlockedFrame{ 225 Type: protocol.StreamTypeBidi, 226 StreamLimit: 0x1234567, 227 } 228 b, err := f.Append(nil, protocol.Version1) 229 Expect(err).ToNot(HaveOccurred()) 230 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 231 Expect(err).ToNot(HaveOccurred()) 232 Expect(frame).To(Equal(f)) 233 Expect(l).To(Equal(len(b))) 234 }) 235 236 It("unpacks NEW_CONNECTION_ID frames", func() { 237 f := &NewConnectionIDFrame{ 238 SequenceNumber: 0x1337, 239 ConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}), 240 StatelessResetToken: protocol.StatelessResetToken{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, 241 } 242 b, err := f.Append(nil, protocol.Version1) 243 Expect(err).ToNot(HaveOccurred()) 244 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 245 Expect(err).ToNot(HaveOccurred()) 246 Expect(frame).To(Equal(f)) 247 Expect(l).To(Equal(len(b))) 248 }) 249 250 It("unpacks RETIRE_CONNECTION_ID frames", func() { 251 f := &RetireConnectionIDFrame{SequenceNumber: 0x1337} 252 b, err := f.Append(nil, protocol.Version1) 253 Expect(err).ToNot(HaveOccurred()) 254 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 255 Expect(err).ToNot(HaveOccurred()) 256 Expect(frame).To(Equal(f)) 257 Expect(l).To(Equal(len(b))) 258 }) 259 260 It("unpacks PATH_CHALLENGE frames", func() { 261 f := &PathChallengeFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}} 262 b, err := f.Append(nil, protocol.Version1) 263 Expect(err).ToNot(HaveOccurred()) 264 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 265 Expect(err).ToNot(HaveOccurred()) 266 Expect(frame).ToNot(BeNil()) 267 Expect(frame).To(BeAssignableToTypeOf(f)) 268 Expect(frame.(*PathChallengeFrame).Data).To(Equal([8]byte{1, 2, 3, 4, 5, 6, 7, 8})) 269 Expect(l).To(Equal(len(b))) 270 }) 271 272 It("unpacks PATH_RESPONSE frames", func() { 273 f := &PathResponseFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}} 274 b, err := f.Append(nil, protocol.Version1) 275 Expect(err).ToNot(HaveOccurred()) 276 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 277 Expect(err).ToNot(HaveOccurred()) 278 Expect(frame).ToNot(BeNil()) 279 Expect(frame).To(BeAssignableToTypeOf(f)) 280 Expect(frame.(*PathResponseFrame).Data).To(Equal([8]byte{1, 2, 3, 4, 5, 6, 7, 8})) 281 Expect(l).To(Equal(len(b))) 282 }) 283 284 It("unpacks CONNECTION_CLOSE frames", func() { 285 f := &ConnectionCloseFrame{ 286 IsApplicationError: true, 287 ReasonPhrase: "foobar", 288 } 289 b, err := f.Append(nil, protocol.Version1) 290 Expect(err).ToNot(HaveOccurred()) 291 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 292 Expect(err).ToNot(HaveOccurred()) 293 Expect(frame).To(Equal(f)) 294 Expect(l).To(Equal(len(b))) 295 }) 296 297 It("unpacks HANDSHAKE_DONE frames", func() { 298 f := &HandshakeDoneFrame{} 299 b, err := f.Append(nil, protocol.Version1) 300 Expect(err).ToNot(HaveOccurred()) 301 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 302 Expect(err).ToNot(HaveOccurred()) 303 Expect(frame).To(Equal(f)) 304 Expect(l).To(Equal(len(b))) 305 }) 306 307 It("unpacks DATAGRAM frames", func() { 308 f := &DatagramFrame{Data: []byte("foobar")} 309 b, err := f.Append(nil, protocol.Version1) 310 Expect(err).ToNot(HaveOccurred()) 311 l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 312 Expect(err).ToNot(HaveOccurred()) 313 Expect(frame).To(Equal(f)) 314 Expect(l).To(Equal(len(b))) 315 }) 316 317 It("errors when DATAGRAM frames are not supported", func() { 318 parser = *NewFrameParser(false) 319 f := &DatagramFrame{Data: []byte("foobar")} 320 b, err := f.Append(nil, protocol.Version1) 321 Expect(err).ToNot(HaveOccurred()) 322 _, _, err = parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 323 Expect(err).To(MatchError(&qerr.TransportError{ 324 ErrorCode: qerr.FrameEncodingError, 325 FrameType: 0x30, 326 ErrorMessage: "unknown frame type", 327 })) 328 }) 329 330 It("errors on invalid type", func() { 331 _, _, err := parser.ParseNext(encodeVarInt(0x42), protocol.Encryption1RTT, protocol.Version1) 332 Expect(err).To(MatchError(&qerr.TransportError{ 333 ErrorCode: qerr.FrameEncodingError, 334 FrameType: 0x42, 335 ErrorMessage: "unknown frame type", 336 })) 337 }) 338 339 It("errors on invalid frames", func() { 340 f := &MaxStreamDataFrame{ 341 StreamID: 0x1337, 342 MaximumStreamData: 0xdeadbeef, 343 } 344 b, err := f.Append(nil, protocol.Version1) 345 Expect(err).ToNot(HaveOccurred()) 346 _, _, err = parser.ParseNext(b[:len(b)-2], protocol.Encryption1RTT, protocol.Version1) 347 Expect(err).To(HaveOccurred()) 348 Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError)) 349 }) 350 351 Context("encryption level check", func() { 352 frames := []Frame{ 353 &PingFrame{}, 354 &AckFrame{AckRanges: []AckRange{{Smallest: 1, Largest: 42}}}, 355 &ResetStreamFrame{}, 356 &StopSendingFrame{}, 357 &CryptoFrame{}, 358 &NewTokenFrame{Token: []byte("lorem ipsum")}, 359 &StreamFrame{Data: []byte("foobar")}, 360 &MaxDataFrame{}, 361 &MaxStreamDataFrame{}, 362 &MaxStreamsFrame{}, 363 &DataBlockedFrame{}, 364 &StreamDataBlockedFrame{}, 365 &StreamsBlockedFrame{}, 366 &NewConnectionIDFrame{ConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef})}, 367 &RetireConnectionIDFrame{}, 368 &PathChallengeFrame{}, 369 &PathResponseFrame{}, 370 &ConnectionCloseFrame{}, 371 &HandshakeDoneFrame{}, 372 &DatagramFrame{}, 373 } 374 375 var framesSerialized [][]byte 376 377 BeforeEach(func() { 378 framesSerialized = nil 379 for _, frame := range frames { 380 b, err := frame.Append(nil, protocol.Version1) 381 Expect(err).ToNot(HaveOccurred()) 382 framesSerialized = append(framesSerialized, b) 383 } 384 }) 385 386 It("rejects all frames but ACK, CRYPTO, PING and CONNECTION_CLOSE in Initial packets", func() { 387 for i, b := range framesSerialized { 388 _, _, err := parser.ParseNext(b, protocol.EncryptionInitial, protocol.Version1) 389 switch frames[i].(type) { 390 case *AckFrame, *ConnectionCloseFrame, *CryptoFrame, *PingFrame: 391 Expect(err).ToNot(HaveOccurred()) 392 default: 393 Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{})) 394 Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError)) 395 Expect(err.(*qerr.TransportError).ErrorMessage).To(ContainSubstring("not allowed at encryption level Initial")) 396 } 397 } 398 }) 399 400 It("rejects all frames but ACK, CRYPTO, PING and CONNECTION_CLOSE in Handshake packets", func() { 401 for i, b := range framesSerialized { 402 _, _, err := parser.ParseNext(b, protocol.EncryptionHandshake, protocol.Version1) 403 switch frames[i].(type) { 404 case *AckFrame, *ConnectionCloseFrame, *CryptoFrame, *PingFrame: 405 Expect(err).ToNot(HaveOccurred()) 406 default: 407 Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{})) 408 Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError)) 409 Expect(err.(*qerr.TransportError).ErrorMessage).To(ContainSubstring("not allowed at encryption level Handshake")) 410 } 411 } 412 }) 413 414 It("rejects all frames but ACK, CRYPTO, CONNECTION_CLOSE, NEW_TOKEN, PATH_RESPONSE and RETIRE_CONNECTION_ID in 0-RTT packets", func() { 415 for i, b := range framesSerialized { 416 _, _, err := parser.ParseNext(b, protocol.Encryption0RTT, protocol.Version1) 417 switch frames[i].(type) { 418 case *AckFrame, *ConnectionCloseFrame, *CryptoFrame, *NewTokenFrame, *PathResponseFrame, *RetireConnectionIDFrame: 419 Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{})) 420 Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError)) 421 Expect(err.(*qerr.TransportError).ErrorMessage).To(ContainSubstring("not allowed at encryption level 0-RTT")) 422 default: 423 Expect(err).ToNot(HaveOccurred()) 424 } 425 } 426 }) 427 428 It("accepts all frame types in 1-RTT packets", func() { 429 for _, b := range framesSerialized { 430 _, _, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1) 431 Expect(err).ToNot(HaveOccurred()) 432 } 433 }) 434 }) 435 })