github.com/quic-go/quic-go@v0.44.0/internal/wire/frame_parser_test.go (about)

     1  package wire
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  	"time"
     7  
     8  	"golang.org/x/exp/rand"
     9  
    10  	"github.com/quic-go/quic-go/internal/protocol"
    11  	"github.com/quic-go/quic-go/internal/qerr"
    12  
    13  	. "github.com/onsi/ginkgo/v2"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  var _ = Describe("Frame parsing", func() {
    18  	var parser FrameParser
    19  
    20  	BeforeEach(func() {
    21  		parser = *NewFrameParser(true)
    22  	})
    23  
    24  	It("returns nil if there's nothing more to read", func() {
    25  		l, f, err := parser.ParseNext(nil, protocol.Encryption1RTT, protocol.Version1)
    26  		Expect(err).ToNot(HaveOccurred())
    27  		Expect(l).To(BeZero())
    28  		Expect(f).To(BeNil())
    29  	})
    30  
    31  	It("skips PADDING frames", func() {
    32  		b := []byte{0, 0} // 2 PADDING frames
    33  		b, err := (&PingFrame{}).Append(b, protocol.Version1)
    34  		Expect(err).ToNot(HaveOccurred())
    35  		l, f, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
    36  		Expect(err).ToNot(HaveOccurred())
    37  		Expect(f).To(Equal(&PingFrame{}))
    38  		Expect(l).To(Equal(2 + 1))
    39  	})
    40  
    41  	It("handles PADDING at the end", func() {
    42  		l, f, err := parser.ParseNext([]byte{0, 0, 0}, protocol.Encryption1RTT, protocol.Version1)
    43  		Expect(err).ToNot(HaveOccurred())
    44  		Expect(f).To(BeNil())
    45  		Expect(l).To(Equal(3))
    46  	})
    47  
    48  	It("parses a single frame", func() {
    49  		var b []byte
    50  		for i := 0; i < 10; i++ {
    51  			var err error
    52  			b, err = (&PingFrame{}).Append(b, protocol.Version1)
    53  			Expect(err).ToNot(HaveOccurred())
    54  		}
    55  		l, f, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
    56  		Expect(err).ToNot(HaveOccurred())
    57  		Expect(f).To(BeAssignableToTypeOf(&PingFrame{}))
    58  		Expect(l).To(Equal(1))
    59  	})
    60  
    61  	It("unpacks ACK frames", func() {
    62  		f := &AckFrame{AckRanges: []AckRange{{Smallest: 1, Largest: 0x13}}}
    63  		b, err := f.Append(nil, protocol.Version1)
    64  		Expect(err).ToNot(HaveOccurred())
    65  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
    66  		Expect(err).ToNot(HaveOccurred())
    67  		Expect(frame).ToNot(BeNil())
    68  		Expect(frame).To(BeAssignableToTypeOf(f))
    69  		Expect(frame.(*AckFrame).LargestAcked()).To(Equal(protocol.PacketNumber(0x13)))
    70  		Expect(l).To(Equal(len(b)))
    71  	})
    72  
    73  	It("uses the custom ack delay exponent for 1RTT packets", func() {
    74  		parser.SetAckDelayExponent(protocol.AckDelayExponent + 2)
    75  		f := &AckFrame{
    76  			AckRanges: []AckRange{{Smallest: 1, Largest: 1}},
    77  			DelayTime: time.Second,
    78  		}
    79  		b, err := f.Append(nil, protocol.Version1)
    80  		Expect(err).ToNot(HaveOccurred())
    81  		_, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
    82  		Expect(err).ToNot(HaveOccurred())
    83  		// The ACK frame is always written using the protocol.AckDelayExponent.
    84  		// That's why we expect a different value when parsing.
    85  		Expect(frame.(*AckFrame).DelayTime).To(Equal(4 * time.Second))
    86  	})
    87  
    88  	It("uses the default ack delay exponent for non-1RTT packets", func() {
    89  		parser.SetAckDelayExponent(protocol.AckDelayExponent + 2)
    90  		f := &AckFrame{
    91  			AckRanges: []AckRange{{Smallest: 1, Largest: 1}},
    92  			DelayTime: time.Second,
    93  		}
    94  		b, err := f.Append(nil, protocol.Version1)
    95  		Expect(err).ToNot(HaveOccurred())
    96  		_, frame, err := parser.ParseNext(b, protocol.EncryptionHandshake, protocol.Version1)
    97  		Expect(err).ToNot(HaveOccurred())
    98  		Expect(frame.(*AckFrame).DelayTime).To(Equal(time.Second))
    99  	})
   100  
   101  	It("unpacks RESET_STREAM frames", func() {
   102  		f := &ResetStreamFrame{
   103  			StreamID:  0xdeadbeef,
   104  			FinalSize: 0xdecafbad1234,
   105  			ErrorCode: 0x1337,
   106  		}
   107  		b, err := f.Append(nil, protocol.Version1)
   108  		Expect(err).ToNot(HaveOccurred())
   109  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   110  		Expect(err).ToNot(HaveOccurred())
   111  		Expect(frame).To(Equal(f))
   112  		Expect(l).To(Equal(len(b)))
   113  	})
   114  
   115  	It("unpacks STOP_SENDING frames", func() {
   116  		f := &StopSendingFrame{StreamID: 0x42}
   117  		b, err := f.Append(nil, protocol.Version1)
   118  		Expect(err).ToNot(HaveOccurred())
   119  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   120  		Expect(err).ToNot(HaveOccurred())
   121  		Expect(frame).To(Equal(f))
   122  		Expect(l).To(Equal(len(b)))
   123  	})
   124  
   125  	It("unpacks CRYPTO frames", func() {
   126  		f := &CryptoFrame{
   127  			Offset: 0x1337,
   128  			Data:   []byte("lorem ipsum"),
   129  		}
   130  		b, err := f.Append(nil, protocol.Version1)
   131  		Expect(err).ToNot(HaveOccurred())
   132  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   133  		Expect(err).ToNot(HaveOccurred())
   134  		Expect(frame).ToNot(BeNil())
   135  		Expect(frame).To(Equal(f))
   136  		Expect(l).To(Equal(len(b)))
   137  	})
   138  
   139  	It("unpacks NEW_TOKEN frames", func() {
   140  		f := &NewTokenFrame{Token: []byte("foobar")}
   141  		b, err := f.Append(nil, protocol.Version1)
   142  		Expect(err).ToNot(HaveOccurred())
   143  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   144  		Expect(err).ToNot(HaveOccurred())
   145  		Expect(frame).ToNot(BeNil())
   146  		Expect(frame).To(Equal(f))
   147  		Expect(l).To(Equal(len(b)))
   148  	})
   149  
   150  	It("unpacks STREAM frames", func() {
   151  		f := &StreamFrame{
   152  			StreamID: 0x42,
   153  			Offset:   0x1337,
   154  			Fin:      true,
   155  			Data:     []byte("foobar"),
   156  		}
   157  		b, err := f.Append(nil, protocol.Version1)
   158  		Expect(err).ToNot(HaveOccurred())
   159  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   160  		Expect(err).ToNot(HaveOccurred())
   161  		Expect(frame).ToNot(BeNil())
   162  		Expect(frame).To(Equal(f))
   163  		Expect(l).To(Equal(len(b)))
   164  	})
   165  
   166  	It("unpacks MAX_DATA frames", func() {
   167  		f := &MaxDataFrame{
   168  			MaximumData: 0xcafe,
   169  		}
   170  		b, err := f.Append(nil, protocol.Version1)
   171  		Expect(err).ToNot(HaveOccurred())
   172  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   173  		Expect(err).ToNot(HaveOccurred())
   174  		Expect(frame).To(Equal(f))
   175  		Expect(l).To(Equal(len(b)))
   176  	})
   177  
   178  	It("unpacks MAX_STREAM_DATA frames", func() {
   179  		f := &MaxStreamDataFrame{
   180  			StreamID:          0xdeadbeef,
   181  			MaximumStreamData: 0xdecafbad,
   182  		}
   183  		b, err := f.Append(nil, protocol.Version1)
   184  		Expect(err).ToNot(HaveOccurred())
   185  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   186  		Expect(err).ToNot(HaveOccurred())
   187  		Expect(frame).To(Equal(f))
   188  		Expect(l).To(Equal(len(b)))
   189  	})
   190  
   191  	It("unpacks MAX_STREAMS frames", func() {
   192  		f := &MaxStreamsFrame{
   193  			Type:         protocol.StreamTypeBidi,
   194  			MaxStreamNum: 0x1337,
   195  		}
   196  		b, err := f.Append(nil, protocol.Version1)
   197  		Expect(err).ToNot(HaveOccurred())
   198  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   199  		Expect(err).ToNot(HaveOccurred())
   200  		Expect(frame).To(Equal(f))
   201  		Expect(l).To(Equal(len(b)))
   202  	})
   203  
   204  	It("unpacks DATA_BLOCKED frames", func() {
   205  		f := &DataBlockedFrame{MaximumData: 0x1234}
   206  		b, err := f.Append(nil, protocol.Version1)
   207  		Expect(err).ToNot(HaveOccurred())
   208  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   209  		Expect(err).ToNot(HaveOccurred())
   210  		Expect(frame).To(Equal(f))
   211  		Expect(l).To(Equal(len(b)))
   212  	})
   213  
   214  	It("unpacks STREAM_DATA_BLOCKED frames", func() {
   215  		f := &StreamDataBlockedFrame{
   216  			StreamID:          0xdeadbeef,
   217  			MaximumStreamData: 0xdead,
   218  		}
   219  		b, err := f.Append(nil, protocol.Version1)
   220  		Expect(err).ToNot(HaveOccurred())
   221  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   222  		Expect(err).ToNot(HaveOccurred())
   223  		Expect(frame).To(Equal(f))
   224  		Expect(l).To(Equal(len(b)))
   225  	})
   226  
   227  	It("unpacks STREAMS_BLOCKED frames", func() {
   228  		f := &StreamsBlockedFrame{
   229  			Type:        protocol.StreamTypeBidi,
   230  			StreamLimit: 0x1234567,
   231  		}
   232  		b, err := f.Append(nil, protocol.Version1)
   233  		Expect(err).ToNot(HaveOccurred())
   234  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   235  		Expect(err).ToNot(HaveOccurred())
   236  		Expect(frame).To(Equal(f))
   237  		Expect(l).To(Equal(len(b)))
   238  	})
   239  
   240  	It("unpacks NEW_CONNECTION_ID frames", func() {
   241  		f := &NewConnectionIDFrame{
   242  			SequenceNumber:      0x1337,
   243  			ConnectionID:        protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}),
   244  			StatelessResetToken: protocol.StatelessResetToken{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
   245  		}
   246  		b, err := f.Append(nil, protocol.Version1)
   247  		Expect(err).ToNot(HaveOccurred())
   248  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   249  		Expect(err).ToNot(HaveOccurred())
   250  		Expect(frame).To(Equal(f))
   251  		Expect(l).To(Equal(len(b)))
   252  	})
   253  
   254  	It("unpacks RETIRE_CONNECTION_ID frames", func() {
   255  		f := &RetireConnectionIDFrame{SequenceNumber: 0x1337}
   256  		b, err := f.Append(nil, protocol.Version1)
   257  		Expect(err).ToNot(HaveOccurred())
   258  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   259  		Expect(err).ToNot(HaveOccurred())
   260  		Expect(frame).To(Equal(f))
   261  		Expect(l).To(Equal(len(b)))
   262  	})
   263  
   264  	It("unpacks PATH_CHALLENGE frames", func() {
   265  		f := &PathChallengeFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}
   266  		b, err := f.Append(nil, protocol.Version1)
   267  		Expect(err).ToNot(HaveOccurred())
   268  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   269  		Expect(err).ToNot(HaveOccurred())
   270  		Expect(frame).ToNot(BeNil())
   271  		Expect(frame).To(BeAssignableToTypeOf(f))
   272  		Expect(frame.(*PathChallengeFrame).Data).To(Equal([8]byte{1, 2, 3, 4, 5, 6, 7, 8}))
   273  		Expect(l).To(Equal(len(b)))
   274  	})
   275  
   276  	It("unpacks PATH_RESPONSE frames", func() {
   277  		f := &PathResponseFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}
   278  		b, err := f.Append(nil, protocol.Version1)
   279  		Expect(err).ToNot(HaveOccurred())
   280  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   281  		Expect(err).ToNot(HaveOccurred())
   282  		Expect(frame).ToNot(BeNil())
   283  		Expect(frame).To(BeAssignableToTypeOf(f))
   284  		Expect(frame.(*PathResponseFrame).Data).To(Equal([8]byte{1, 2, 3, 4, 5, 6, 7, 8}))
   285  		Expect(l).To(Equal(len(b)))
   286  	})
   287  
   288  	It("unpacks CONNECTION_CLOSE frames", func() {
   289  		f := &ConnectionCloseFrame{
   290  			IsApplicationError: true,
   291  			ReasonPhrase:       "foobar",
   292  		}
   293  		b, err := f.Append(nil, protocol.Version1)
   294  		Expect(err).ToNot(HaveOccurred())
   295  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   296  		Expect(err).ToNot(HaveOccurred())
   297  		Expect(frame).To(Equal(f))
   298  		Expect(l).To(Equal(len(b)))
   299  	})
   300  
   301  	It("unpacks HANDSHAKE_DONE frames", func() {
   302  		f := &HandshakeDoneFrame{}
   303  		b, err := f.Append(nil, protocol.Version1)
   304  		Expect(err).ToNot(HaveOccurred())
   305  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   306  		Expect(err).ToNot(HaveOccurred())
   307  		Expect(frame).To(Equal(f))
   308  		Expect(l).To(Equal(len(b)))
   309  	})
   310  
   311  	It("unpacks DATAGRAM frames", func() {
   312  		f := &DatagramFrame{Data: []byte("foobar")}
   313  		b, err := f.Append(nil, protocol.Version1)
   314  		Expect(err).ToNot(HaveOccurred())
   315  		l, frame, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   316  		Expect(err).ToNot(HaveOccurred())
   317  		Expect(frame).To(Equal(f))
   318  		Expect(l).To(Equal(len(b)))
   319  	})
   320  
   321  	It("errors when DATAGRAM frames are not supported", func() {
   322  		parser = *NewFrameParser(false)
   323  		f := &DatagramFrame{Data: []byte("foobar")}
   324  		b, err := f.Append(nil, protocol.Version1)
   325  		Expect(err).ToNot(HaveOccurred())
   326  		_, _, err = parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   327  		Expect(err).To(MatchError(&qerr.TransportError{
   328  			ErrorCode:    qerr.FrameEncodingError,
   329  			FrameType:    0x30,
   330  			ErrorMessage: "unknown frame type",
   331  		}))
   332  	})
   333  
   334  	It("errors on invalid type", func() {
   335  		_, _, err := parser.ParseNext(encodeVarInt(0x42), protocol.Encryption1RTT, protocol.Version1)
   336  		Expect(err).To(MatchError(&qerr.TransportError{
   337  			ErrorCode:    qerr.FrameEncodingError,
   338  			FrameType:    0x42,
   339  			ErrorMessage: "unknown frame type",
   340  		}))
   341  	})
   342  
   343  	It("errors on invalid frames", func() {
   344  		f := &MaxStreamDataFrame{
   345  			StreamID:          0x1337,
   346  			MaximumStreamData: 0xdeadbeef,
   347  		}
   348  		b, err := f.Append(nil, protocol.Version1)
   349  		Expect(err).ToNot(HaveOccurred())
   350  		_, _, err = parser.ParseNext(b[:len(b)-2], protocol.Encryption1RTT, protocol.Version1)
   351  		Expect(err).To(HaveOccurred())
   352  		Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError))
   353  	})
   354  
   355  	Context("encryption level check", func() {
   356  		frames := []Frame{
   357  			&PingFrame{},
   358  			&AckFrame{AckRanges: []AckRange{{Smallest: 1, Largest: 42}}},
   359  			&ResetStreamFrame{},
   360  			&StopSendingFrame{},
   361  			&CryptoFrame{},
   362  			&NewTokenFrame{Token: []byte("lorem ipsum")},
   363  			&StreamFrame{Data: []byte("foobar")},
   364  			&MaxDataFrame{},
   365  			&MaxStreamDataFrame{},
   366  			&MaxStreamsFrame{},
   367  			&DataBlockedFrame{},
   368  			&StreamDataBlockedFrame{},
   369  			&StreamsBlockedFrame{},
   370  			&NewConnectionIDFrame{ConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef})},
   371  			&RetireConnectionIDFrame{},
   372  			&PathChallengeFrame{},
   373  			&PathResponseFrame{},
   374  			&ConnectionCloseFrame{},
   375  			&HandshakeDoneFrame{},
   376  			&DatagramFrame{},
   377  		}
   378  
   379  		var framesSerialized [][]byte
   380  
   381  		BeforeEach(func() {
   382  			framesSerialized = nil
   383  			for _, frame := range frames {
   384  				b, err := frame.Append(nil, protocol.Version1)
   385  				Expect(err).ToNot(HaveOccurred())
   386  				framesSerialized = append(framesSerialized, b)
   387  			}
   388  		})
   389  
   390  		It("rejects all frames but ACK, CRYPTO, PING and CONNECTION_CLOSE in Initial packets", func() {
   391  			for i, b := range framesSerialized {
   392  				_, _, err := parser.ParseNext(b, protocol.EncryptionInitial, protocol.Version1)
   393  				switch frames[i].(type) {
   394  				case *AckFrame, *ConnectionCloseFrame, *CryptoFrame, *PingFrame:
   395  					Expect(err).ToNot(HaveOccurred())
   396  				default:
   397  					Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{}))
   398  					Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError))
   399  					Expect(err.(*qerr.TransportError).ErrorMessage).To(ContainSubstring("not allowed at encryption level Initial"))
   400  				}
   401  			}
   402  		})
   403  
   404  		It("rejects all frames but ACK, CRYPTO, PING and CONNECTION_CLOSE in Handshake packets", func() {
   405  			for i, b := range framesSerialized {
   406  				_, _, err := parser.ParseNext(b, protocol.EncryptionHandshake, protocol.Version1)
   407  				switch frames[i].(type) {
   408  				case *AckFrame, *ConnectionCloseFrame, *CryptoFrame, *PingFrame:
   409  					Expect(err).ToNot(HaveOccurred())
   410  				default:
   411  					Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{}))
   412  					Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError))
   413  					Expect(err.(*qerr.TransportError).ErrorMessage).To(ContainSubstring("not allowed at encryption level Handshake"))
   414  				}
   415  			}
   416  		})
   417  
   418  		It("rejects all frames but ACK, CRYPTO, CONNECTION_CLOSE, NEW_TOKEN, PATH_RESPONSE and RETIRE_CONNECTION_ID in 0-RTT packets", func() {
   419  			for i, b := range framesSerialized {
   420  				_, _, err := parser.ParseNext(b, protocol.Encryption0RTT, protocol.Version1)
   421  				switch frames[i].(type) {
   422  				case *AckFrame, *ConnectionCloseFrame, *CryptoFrame, *NewTokenFrame, *PathResponseFrame, *RetireConnectionIDFrame:
   423  					Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{}))
   424  					Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.FrameEncodingError))
   425  					Expect(err.(*qerr.TransportError).ErrorMessage).To(ContainSubstring("not allowed at encryption level 0-RTT"))
   426  				default:
   427  					Expect(err).ToNot(HaveOccurred())
   428  				}
   429  			}
   430  		})
   431  
   432  		It("accepts all frame types in 1-RTT packets", func() {
   433  			for _, b := range framesSerialized {
   434  				_, _, err := parser.ParseNext(b, protocol.Encryption1RTT, protocol.Version1)
   435  				Expect(err).ToNot(HaveOccurred())
   436  			}
   437  		})
   438  	})
   439  })
   440  
   441  // STREAM and ACK are the most relevant frames for high-throughput transfers.
   442  func BenchmarkParseStreamAndACK(b *testing.B) {
   443  	ack := &AckFrame{
   444  		AckRanges: []AckRange{
   445  			{Smallest: 5000, Largest: 5200},
   446  			{Smallest: 1, Largest: 4200},
   447  		},
   448  		DelayTime: 42 * time.Millisecond,
   449  		ECT0:      5000,
   450  		ECT1:      0,
   451  		ECNCE:     10,
   452  	}
   453  	sf := &StreamFrame{
   454  		StreamID:       1337,
   455  		Offset:         1e7,
   456  		Data:           make([]byte, 200),
   457  		DataLenPresent: true,
   458  	}
   459  	rand.Read(sf.Data)
   460  
   461  	data, err := ack.Append([]byte{}, protocol.Version1)
   462  	if err != nil {
   463  		b.Fatal(err)
   464  	}
   465  	data, err = sf.Append(data, protocol.Version1)
   466  	if err != nil {
   467  		b.Fatal(err)
   468  	}
   469  
   470  	parser := NewFrameParser(false)
   471  	parser.SetAckDelayExponent(3)
   472  
   473  	b.ResetTimer()
   474  	b.ReportAllocs()
   475  	for i := 0; i < b.N; i++ {
   476  		l, f, err := parser.ParseNext(data, protocol.Encryption1RTT, protocol.Version1)
   477  		if err != nil {
   478  			b.Fatal(err)
   479  		}
   480  		ackParsed := f.(*AckFrame)
   481  		if ackParsed.DelayTime != ack.DelayTime || ackParsed.ECNCE != ack.ECNCE {
   482  			b.Fatalf("incorrect ACK frame: %v vs %v", ack, ackParsed)
   483  		}
   484  		l2, f, err := parser.ParseNext(data[l:], protocol.Encryption1RTT, protocol.Version1)
   485  		if err != nil {
   486  			b.Fatal(err)
   487  		}
   488  		if len(data[l:]) != l2 {
   489  			b.Fatal("didn't parse the entire packet")
   490  		}
   491  		sfParsed := f.(*StreamFrame)
   492  		if sfParsed.StreamID != sf.StreamID || !bytes.Equal(sfParsed.Data, sf.Data) {
   493  			b.Fatalf("incorrect STREAM frame: %v vs %v", sf, sfParsed)
   494  		}
   495  	}
   496  }
   497  
   498  func BenchmarkParseOtherFrames(b *testing.B) {
   499  	maxDataFrame := &MaxDataFrame{MaximumData: 123456}
   500  	maxStreamsFrame := &MaxStreamsFrame{MaxStreamNum: 10}
   501  	maxStreamDataFrame := &MaxStreamDataFrame{StreamID: 1337, MaximumStreamData: 1e6}
   502  	cryptoFrame := &CryptoFrame{Offset: 1000, Data: make([]byte, 128)}
   503  	resetStreamFrame := &ResetStreamFrame{StreamID: 87654, ErrorCode: 1234, FinalSize: 1e8}
   504  	rand.Read(cryptoFrame.Data)
   505  	frames := []Frame{
   506  		maxDataFrame,
   507  		maxStreamsFrame,
   508  		maxStreamDataFrame,
   509  		cryptoFrame,
   510  		&PingFrame{},
   511  		resetStreamFrame,
   512  	}
   513  	var buf []byte
   514  	for i, frame := range frames {
   515  		var err error
   516  		buf, err = frame.Append(buf, protocol.Version1)
   517  		if err != nil {
   518  			b.Fatal(err)
   519  		}
   520  		if i == len(frames)/2 {
   521  			// add 3 PADDING frames
   522  			buf = append(buf, 0)
   523  			buf = append(buf, 0)
   524  			buf = append(buf, 0)
   525  		}
   526  	}
   527  
   528  	parser := NewFrameParser(false)
   529  
   530  	b.ResetTimer()
   531  	b.ReportAllocs()
   532  	for i := 0; i < b.N; i++ {
   533  		data := buf
   534  		for j := 0; j < len(frames); j++ {
   535  			l, f, err := parser.ParseNext(data, protocol.Encryption1RTT, protocol.Version1)
   536  			if err != nil {
   537  				b.Fatal(err)
   538  			}
   539  			data = data[l:]
   540  			switch j {
   541  			case 0:
   542  				if f.(*MaxDataFrame).MaximumData != maxDataFrame.MaximumData {
   543  					b.Fatalf("MAX_DATA frame does not match: %v vs %v", f, maxDataFrame)
   544  				}
   545  			case 1:
   546  				if f.(*MaxStreamsFrame).MaxStreamNum != maxStreamsFrame.MaxStreamNum {
   547  					b.Fatalf("MAX_STREAMS frame does not match: %v vs %v", f, maxStreamsFrame)
   548  				}
   549  			case 2:
   550  				if f.(*MaxStreamDataFrame).StreamID != maxStreamDataFrame.StreamID ||
   551  					f.(*MaxStreamDataFrame).MaximumStreamData != maxStreamDataFrame.MaximumStreamData {
   552  					b.Fatalf("MAX_STREAM_DATA frame does not match: %v vs %v", f, maxStreamDataFrame)
   553  				}
   554  			case 3:
   555  				if f.(*CryptoFrame).Offset != cryptoFrame.Offset || !bytes.Equal(f.(*CryptoFrame).Data, cryptoFrame.Data) {
   556  					b.Fatalf("CRYPTO frame does not match: %v vs %v", f, cryptoFrame)
   557  				}
   558  			case 4:
   559  				_ = f.(*PingFrame)
   560  			case 5:
   561  				rst := f.(*ResetStreamFrame)
   562  				if rst.StreamID != resetStreamFrame.StreamID || rst.ErrorCode != resetStreamFrame.ErrorCode ||
   563  					rst.FinalSize != resetStreamFrame.FinalSize {
   564  					b.Fatalf("RESET_STREAM frame does not match: %v vs %v", rst, resetStreamFrame)
   565  				}
   566  			}
   567  		}
   568  	}
   569  }