github.com/daeuniverse/quic-go@v0.0.0-20240413031024-943f218e0810/internal/wire/frame_parser_test.go (about)

     1  package wire
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/daeuniverse/quic-go/internal/protocol"
     7  	"github.com/daeuniverse/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  })